├── .gitignore ├── LICENSE ├── README.md ├── config └── onboard_do.json ├── examples ├── bigip_gcp_1nic_deploy │ ├── main.tf │ ├── output.tf │ ├── terraform.tfvars │ └── variables.tf ├── bigip_gcp_1nic_deploy_custom_runtime_init │ ├── custom_onboard_big.tpl │ ├── main.tf │ ├── output.tf │ ├── terraform.tfvars │ └── variables.tf ├── bigip_gcp_1nic_deploy_provider_integration │ ├── bigip.tf │ ├── main.tf │ ├── output.tf │ ├── terraform.tfvars │ └── variables.tf ├── bigip_gcp_2nic_deploy │ ├── main.tf │ ├── output.tf │ ├── terraform.tfvars │ └── variables.tf ├── bigip_gcp_3nic_deploy │ ├── main.tf │ ├── output.tf │ ├── terraform.tfvars │ ├── ubunturun.sh │ └── variables.tf ├── bigip_gcp_4nic_deploy │ ├── main.tf │ ├── output.tf │ ├── terraform.tfvars │ └── variables.tf └── terraform-webserver │ ├── outputs.tf │ ├── provider.tf │ ├── template │ └── install_nginx.tpl │ ├── terraform.tfvars │ ├── testflask │ ├── main.tf │ ├── terraform.tfvars │ └── variables.tf │ ├── variables.tf │ └── vm.tf ├── main.tf ├── output.tf ├── startup-script-backup.tpl ├── startup-script-working.tpl ├── startup-script.tpl ├── test ├── gcp_bigip_1nic_unit_test.go ├── gcp_bigip_2nic_unit_test.go ├── gcp_bigip_3nic_unit_test.go ├── go.mod └── go.sum └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | 11 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 12 | # .tfvars files are managed as part of configuration and so should be included in 13 | # version control. 14 | # 15 | # example.tfvars 16 | 17 | # Ignore override files as they are usually used to override resources locally and so 18 | # are not checked in 19 | override.tf 20 | override.tf.json 21 | *_override.tf 22 | *_override.tf.json 23 | 24 | # Include override files you do wish to add to version control using negated pattern 25 | # 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | 31 | # Ignore CLI configuration files 32 | .terraformrc 33 | terraform.rc 34 | 35 | # Ignore terraform.tfvars since local data is stored there 36 | # **/terraform.tfvars 37 | **/.terraform.lock.hcl -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deploys BIG-IP in GCP Cloud 2 | 3 | This Terraform module deploys N-nic F5 BIG-IP in Gcp cloud,and with module count feature we can also deploy multiple instances of BIG-IP. 4 | 5 | ## Prerequisites 6 | 7 | SSH-Keys : Generate a ssh key pair and keep .pub file in .ssh folder with name id_rsa.pub. 8 | 9 | Getting Started with the Google Provider ( ) 10 | 11 | This module is supported from Terraform 0.13 version onwards. 12 | 13 | Below templates are tested and worked in the following version 14 | 15 | Terraform v0.14.0 16 | 17 | + provider registry.terraform.io/hashicorp/google v4.31.0 18 | + provider registry.terraform.io/hashicorp/null v2.1.2 19 | + provider registry.terraform.io/hashicorp/random v3.0.1 20 | + provider registry.terraform.io/hashicorp/template v2.2.0 21 | 22 | ## Releases and Versioning 23 | 24 | This module is supported in the following bigip and terraform version 25 | 26 | | BIGIP version | Terraform 1.X | Terraform 0.14 | 27 | |---------------|----------------|-----------------| 28 | | BIG-IP 17.x | X | X | 29 | | BIG-IP 16.x | X | X | 30 | | BIG-IP 15.x | X | X | 31 | 32 | ## Password Management 33 | 34 | |:point_up: |By default bigip module will have random password setting to give dynamic password generation| 35 | |----|---| 36 | 37 | |:point_up: |Users Can explicitly provide password as input to Module using optional Variable "f5_password". NOTE: Please don't use admin in password as configuration will fail.| 38 | |----|---| 39 | 40 | |:point_up: | To use Gcp secret manager ,we have to enable the variable "gcp_secret_manager_authentication" to true and supply the variables with secret name,version | 41 | |-----|----| 42 | 43 | ## BYOL Licensing 44 | 45 | This template uses PayGo BIG-IP image for the deployment (as default). If you would like to use BYOL licenses, then these following steps are needed: 46 | 47 | 1.Find available images/versions with "byol" in the name using Google gcloud: 48 | 49 | ```bash 50 | gcloud compute images list --project=f5-7626-networks-public | grep f5 51 | # example output... 52 | --snippet-- 53 | f5-bigip-13-1-3-2-0-0-4-payg-best-1gbps-20191105210022 54 | f5-bigip-13-1-3-2-0-0-4-payg-best-200mbps-20191105210022 55 | f5-bigip-13-1-3-2-0-0-4-byol-all-modules-2slot-20191105200157 56 | ...and some more 57 | f5-bigip-14-1-2-3-0-0-5-byol-ltm-1boot-loc-191218142225 58 | f5-bigip-15-1-2-1-0-0-10-payg-best-1gbps-210115161130 59 | f5-bigip-15-1-2-1-0-0-10-byol-ltm-2boot-loc-210115160742 60 | ...and more... 61 | ``` 62 | 63 | 2.In the "variables.tf", modify image_name with the image name from gcloud CLI results 64 | 65 | ```bash 66 | # BIGIP Image 67 | variable image_name { default = "projects/f5-7626-networks-public/global/images/f5-bigip-15-1-2-1-0-0-10-byol-ltm-2boot-loc-210115160742" } 68 | ``` 69 | 70 | 3.Add the corresponding license key in DO declaration( Declarative Onboarding ), this DO can be in custom run-time-int script or outside of it. 71 | ( ) 72 | 73 | ```bash 74 | "myLicense": { 75 | "class": "License", 76 | "licenseType": "regKey", 77 | "regKey": "${regKey}" 78 | }, 79 | ``` 80 | 81 | ## Custom User data && Metadata 82 | 83 | + By default `custom_user_data` will be `null`,this module will use default [startup-script.tpl](https://github.com/F5Networks/terraform-gcp-bigip-module/blob/main/startup-script.tpl) file contents for initial BIGIP onboard connfiguration 84 | 85 | + If users desire custom onboard configuration,we can use this variable and pass contents of custom script to the `custom_user_data` variable to have custom onboard bigip configuration. ( An example is provided in examples section [custom_user_data](https://github.com/F5Networks/terraform-gcp-bigip-module/tree/main/examples/bigip_gcp_1nic_deploy_custom_runtime_init)) 86 | 87 | + `custom_user_data` script is composed of bash,tmsh and Runtime init yaml file. details of [F5 BIG-IP Runtime Init](https://github.com/F5Networks/f5-bigip-runtime-init) 88 | 89 | ~> **Note:** When user is having `custom_user_data` script, BIG-IP onboard config (like setting users accounts,password setting and additional initial config) completely depends on `custom_user_data` script. 90 | 91 | ### Example 3-NIC deployment with custom_user_data script 92 | 93 | ```hcl 94 | module bigip { 95 | count = var.instance_count 96 | source = "F5Networks/bigip-module/gcp" 97 | prefix = "bigip-gcp-3nic" 98 | project_id = var.project_id 99 | zone = var.zone 100 | image = var.image 101 | service_account = var.service_account 102 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 103 | external_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = true, "private_ip_primary" = "", "private_ip_secondary" = "" }] 104 | internal_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.internal_subnetwork.id, "public_ip" = false, "private_ip_primary" = "", "private_ip_secondary" = "" }] 105 | custom_user_data = var.custom_user_data 106 | } 107 | ``` 108 | 109 | + variable metadata can be used as set of key:value pairs for the instance with or without custom_user_data as shown below 110 | 111 | ```hcl 112 | module "bigip" { 113 | ... 114 | # Onboard through cloud-config YAML and allow connection to serial port 115 | metadata = { 116 | user-data = var.cloud_config_yaml 117 | serial-port-enable = "TRUE" 118 | } 119 | 120 | # Override the module startup-script as everything is in cloud-config YAML 121 | custom_user_data = <<-EOS 122 | #!/bin/sh 123 | exit 0 124 | EOS 125 | } 126 | ``` 127 | 128 | ### Example Usage 129 | 130 | We have provided some common deployment [examples](https://github.com/F5Networks/terraform-gcp-bigip-module/tree/main/examples) 131 | 132 | ~> **Note:** Users can have dynamic or static private ip allocation.If primary/secondary private ip value is null, it will be dynamic or else static private ip allocation. 133 | 134 | ~> **Note:** With Static private ip allocation we can assign primary and secondary private ips for external interfaces, whereas primary private ip for management and internal interfaces. 135 | 136 | If it is static private ip allocation we can't use module count as same private ips will be tried to allocate for multiple 137 | bigip instances based on module count. 138 | 139 | With Dynamic private ip allocation,we have to pass null value to primary/secondary private ip declaration and module count will be supported. 140 | 141 | ~>**NOTE:** If you are using custom ATC tools, don't change name of ATC tools rpm file( ex: f5-declarative-onboarding-xxxx.noarch.rpm,f5-appsvcs-xxx.noarch.rpm) 142 | 143 | Below example snippets show how this module is called. ( Dynamic private ip allocation ) 144 | 145 | ```hcl 146 | #Example 1-NIC Deployment Module usage 147 | module bigip { 148 | count = var.instance_count 149 | source = "F5Networks/bigip-module/gcp" 150 | prefix = "bigip-gcp-1nic" 151 | project_id = var.project_id 152 | zone = var.zone 153 | image = var.image 154 | service_account = var.service_account 155 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 156 | } 157 | NOTE: As per the requirement users can add fields like network_tags, f5_ssh_publickey, f5_password, vm_name, etc. 158 | 159 | #Example 2-NIC Deployment Module usage 160 | 161 | module "bigip" { 162 | count = var.instance_count 163 | source = "F5Networks/bigip-module/gcp" 164 | prefix = "bigip-gcp-2nic" 165 | project_id = var.project_id 166 | zone = var.zone 167 | image = var.image 168 | service_account = var.service_account 169 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 170 | external_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = true, "private_ip_primary" = "", "private_ip_secondary" = "" }] 171 | } 172 | 173 | #Example 3-NIC Deployment Module usage 174 | 175 | module bigip { 176 | count = var.instance_count 177 | source = "F5Networks/bigip-module/gcp" 178 | prefix = "bigip-gcp-3nic" 179 | project_id = var.project_id 180 | zone = var.zone 181 | image = var.image 182 | service_account = var.service_account 183 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 184 | external_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = true, "private_ip_primary" = "", "private_ip_secondary" = "" }] 185 | internal_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.internal_subnetwork.id, "public_ip" = false, "private_ip_primary" = "", "private_ip_secondary" = "" }] 186 | } 187 | 188 | #Example 4-NIC Deployment Module usage(with 2 external public interfaces,one management and internal interfaces) 189 | 190 | module bigip { 191 | count = var.instance_count 192 | source = "F5Networks/bigip-module/gcp" 193 | prefix = "bigip-gcp-4nic" 194 | project_id = var.project_id 195 | zone = var.zone 196 | image = var.image 197 | service_account = var.service_account 198 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 199 | external_subnet_ids = ([{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = true, "private_ip_primary" = "", "private_ip_secondary" = "" }, { "subnet_id" = google_compute_subnetwork.external_subnetwork2.id, "public_ip" = true, "private_ip_primary" = "", "private_ip_secondary" = "" }]) 200 | internal_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.internal_subnetwork.id, "public_ip" = false, "private_ip_primary" = "" }] 201 | } 202 | ``` 203 | 204 | ~>**NOTE:** Similarly we can have N-nic deployments based on user provided subnet_ids. With module count, user can deploy multiple bigip instances in the gcp cloud (with the default value of count being one ) 205 | 206 | ### Below is the example snippet for private ip allocation 207 | 208 | ```hcl 209 | #Example 3-NIC Deployment with static private ip allocation 210 | module bigip { 211 | count = var.instance_count 212 | source = "F5Networks/bigip-module/gcp" 213 | prefix = "bigip-gcp-3nic" 214 | project_id = var.project_id 215 | zone = var.zone 216 | image = var.image 217 | service_account = var.service_account 218 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 219 | external_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = true, "private_ip_primary" = "10.2.1.2", "private_ip_secondary" = "10.2.1.3" }] 220 | internal_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.internal_subnetwork.id, "public_ip" = false, "private_ip_primary" = "", "private_ip_secondary" = "" }] 221 | } 222 | ``` 223 | 224 | #### Required Input Variables 225 | 226 | These variables must be set in the module block when using this module. 227 | 228 | | Name | Description | Type | 229 | |------|-------------|------| 230 | | prefix | This value is inserted in the beginning of each Gcp object. Note: requires alpha-numeric without special character | `string` | 231 | | project\_id | The GCP project identifier where the cluster will be created | `string` | 232 | | zone | The compute zones which will host the BIG-IP VMs | `string` | 233 | | mgmt\_subnet\_ids | Map with Subnet-id and public_ip as keys for the management subnet | `List of Maps` | 234 | | service\_account | service account email to use with BIG-IP | `string` | 235 | 236 | #### Optional Input Variables 237 | 238 | These variables have default values and don't have to be set to use this module. You may set these variables to override their default values. 239 | 240 | | Name | Description | Type | Default | 241 | |------|-------------|------|---------| 242 | | vm\_name | Name of F5 BIGIP VM to be used, default is `empty string` meaning module adds with `prefix + random_id` | `string` | "" | 243 | | f5\_username | The admin username of the F5 BIG-IP that will be deployed | `string` | bigipuser | 244 | | f5\_password | Password of the F5 BIG-IP that will be deployed.If this is not specified random password will get generated | `string` | "" | 245 | | image | The self-link URI for a BIG-IP image to use as a base for the VM cluster | `string` | "projects/f5-7626-networks-public/global/images/f5-bigip-16-0-1-1-0-0-6-payg-good-25mbps-210129040032" | 246 | | min_cpu_platform | Minimum CPU platform for the VM instance such as Intel Haswell or Intel Skylake | `string`| Intel Skylake | 247 | | machine_type | The machine type to create,if you want to update this value (resize the VM) after initial creation, you must set allow_stopping_for_update to true | `string` | n1-standard-4 | 248 | | automatic_restart | Specifies if the instance should be restarted if it was terminated by Compute Engine (not a user) | `bool` | true | 249 | | preemptible | Specifies if the instance is preemptible. If this field is set to true, then automatic_restart must be set to false | `boo1` | false | 250 | | disk_type | The GCE disk type. May be set to pd-standard, pd-balanced or pd-ssd | `string` | pd-ssd | 251 | | disk_size_gb | The size of the image in gigabytes. If not specified, it will inherit the size of its base image | `number` | null | 252 | | gcp_secret_manager_authentication | Whether to use secret manager to pass authentication | `bool` | false | 253 | | gcp_secret_name | The secret to get the secret version for | `string` | null | 254 | | gcp_secret_version | The version of the secret to get. If it is not provided, the latest version is retrieved | `string` | latest| 255 | | libs\_dir | Directory on the BIG-IP to download the A&O Toolchain into | `string` | /config/cloud/gcp/node_modules | 256 | | onboard\_log | Directory on the BIG-IP to store the cloud-init logs | `string` | /var/log/startup-script.log | 257 | | mgmt\_subnet\_ids | List of maps of subnetids of the virtual network where the virtual machines will reside | `List of Maps` | [{ "subnet_id" = null, "public_ip" = null,"private_ip_primary" = "" }] | 258 | | external\_subnet\_ids | List of maps of subnetids of the virtual network where the virtual machines will reside | `List of Maps` | [{ "subnet_id" = null, "public_ip" = null,"private_ip_primary" = "", "private_ip_secondary" = "" }] | 259 | | internal\_subnet\_ids | List of maps of subnetids of the virtual network where the virtual machines will reside | `List of Maps` | [{ "subnet_id" = null, "public_ip" = null,"private_ip_primary" = "" }] | 260 | | DO_URL | URL to download the BIG-IP Declarative Onboarding module | `string` | `latest` Note: don't change name of ATC tools rpm file | 261 | | AS3_URL | URL to download the BIG-IP Application Service Extension 3 (AS3) module | `string` | `latest` Note: don't change name of ATC tools rpm file | 262 | | TS_URL | URL to download the BIG-IP Telemetry Streaming module | `string` | `latest` Note: don't change name of ATC tools rpm file | 263 | | FAST_URL | URL to download the BIG-IP FAST module | `string` | `latest` Note: don't change name of ATC tools rpm file | 264 | | CFE_URL | URL to download the BIG-IP Cloud Failover Extension module | `string` | `latest` Note: don't change name of ATC tools rpm file | 265 | | INIT_URL | URL to download the BIG-IP runtime init module | `string` | `latest` Note: don't change name of ATC tools rpm file | 266 | | custom\_user\_data | Provide a custom bash script or cloud-init script the BIG-IP will run on creation | `string` | null | 267 | | f5_ssh_publickey | Path to the public key to be used for ssh access to the VM. Only used with non-Windows vms and can be left as-is even if using Windows vms. If specifying a path to a certification on a Windows machine to provision a linux vm use the / in the path versus backslash. e.g. c:/home/id_rsa.pub | `string` | ~/.ssh/id_rsa.pub | 268 | | sleep_time | The number of seconds/minutes of delay to build into creation of BIG-IP VMs | `string` | 300s | 269 | | network_tags | The network tags which will be added to the BIG-IP VMs | `list` | [] | 270 | 271 | ~>**NOTE:** `f5_ssh_publickey` is a mandatory parameter, which expects the default ssh .pub file location of `~/.ssh/id_rsa.pub` for ssh access to the VM. Please make sure to have the public key in the path specified or users can use this variable parameter in the module for custom paths. 272 | 273 | #### Output Variables 274 | 275 | | Name | Description | 276 | |------|-------------| 277 | | mgmtPublicIP | The actual ip address allocated for the resource | 278 | | mgmtPort | Mgmt Port | 279 | | f5\_username | BIG-IP username | 280 | | bigip\_password | BIG-IP Password | 281 | | public_addresses | List of BIG-IP public addresses | 282 | | private_addresses | List of BIG-IP private addresses | 283 | | service_account | The service account that will be used for the BIG-IP VMs | 284 | | bigip\_instance\_ids | List of BIG-IP VEs Instance IDs Created in GCP| 285 | 286 | ## Support Information 287 | 288 | This repository is community-supported. Follow instructions below on how to raise issues. 289 | 290 | ### Filing Issues and Getting Help 291 | 292 | If you come across a bug or other issue, use [GitHub Issues](https://github.com/F5Networks/terraform-gcp-bigip-module/issues) to submit an issue for our team. You can also see the current known issues on that page, which are tagged with a purple Known Issue label. 293 | 294 | ## Copyright 295 | 296 | Copyright 2014-2019 F5 Networks Inc. 297 | 298 | ### F5 Networks Contributor License Agreement 299 | 300 | Before you start contributing to any project sponsored by F5 Networks, Inc. (F5) on GitHub, you will need to sign a Contributor License Agreement (CLA). 301 | 302 | If you are signing as an individual, we recommend that you talk to your employer (if applicable) before signing the CLA since some employment agreements may have restrictions on your contributions to other projects. Otherwise by submitting a CLA you represent that you are legally entitled to grant the licenses recited therein. 303 | 304 | If your employer has rights to intellectual property that you create, such as your contributions, you represent that you have received permission to make contributions on behalf of that employer, that your employer has waived such rights for your contributions, or that your employer has executed a separate CLA with F5. 305 | 306 | If you are signing on behalf of a company, you represent that you are legally entitled to grant the license recited therein. You represent further that each employee of the entity that submits contributions is authorized to submit such contributions on behalf of the entity pursuant to the CLA. 307 | -------------------------------------------------------------------------------- /config/onboard_do.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": "1.0.0", 3 | "class": "Device", 4 | "async": true, 5 | "label": "my BIG-IP declaration for declarative onboarding", 6 | "Common": { 7 | "class": "Tenant", 8 | "hostname": "bigip1.example.com", 9 | "myDns": { 10 | "class": "DNS", 11 | "nameServers": [ 12 | "169.254.169.254" 13 | ] 14 | }, 15 | "myNtp": { 16 | "class": "NTP", 17 | "servers": [ 18 | "0.pool.ntp.org" 19 | ], 20 | "timezone": "UTC" 21 | }, 22 | "admin": { 23 | "class": "User", 24 | "userType": "regular", 25 | "password": "{{{ ADMIN_PASS }}}", 26 | "keys": ["{{{ SSH_KEYS }}}"], 27 | "shell": "bash" 28 | }, 29 | "{{{ USER_NAME }}}": { 30 | "class": "User", 31 | "userType": "regular", 32 | "password": "{{{ ADMIN_PASS }}}", 33 | "keys": ["{{{ SSH_KEYS }}}"], 34 | "shell": "bash", 35 | "partitionAccess": { 36 | "all-partitions": { 37 | "role": "admin" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | } 4 | 5 | provider "google" { 6 | project = var.project_id 7 | region = var.region 8 | zone = var.zone 9 | } 10 | 11 | # Create a random id 12 | # 13 | resource "random_id" "id" { 14 | byte_length = 2 15 | } 16 | 17 | # Create random password for BIG-IP 18 | # 19 | resource "random_string" "password" { 20 | length = 16 21 | min_upper = 1 22 | min_lower = 1 23 | min_numeric = 1 24 | special = false 25 | } 26 | 27 | resource "google_compute_network" "vpc" { 28 | name = format("%s-vpc-%s", var.prefix, random_id.id.hex) 29 | auto_create_subnetworks = false 30 | } 31 | 32 | resource "google_compute_subnetwork" "mgmt_subnetwork" { 33 | name = format("%s-mgmt-%s", var.prefix, random_id.id.hex) 34 | ip_cidr_range = "10.1.0.0/24" 35 | region = var.region 36 | network = google_compute_network.vpc.id 37 | } 38 | 39 | resource "google_compute_firewall" "mgmt_firewall" { 40 | name = format("%s-mgmt-firewall-%s", var.prefix, random_id.id.hex) 41 | network = google_compute_network.vpc.id 42 | allow { 43 | protocol = "tcp" 44 | ports = ["22", "80", "443", "8443"] 45 | } 46 | allow { 47 | protocol = "icmp" 48 | } 49 | source_ranges = ["0.0.0.0/0"] 50 | } 51 | 52 | resource "google_service_account" "f5_bigip_user" { 53 | account_id = "f5-bigip-user" 54 | description = "User for F5 BIGIP" 55 | } 56 | 57 | module "bigip" { 58 | count = var.instance_count 59 | source = "../.." 60 | prefix = format("%s-1nic", var.prefix) 61 | project_id = var.project_id 62 | zone = var.zone 63 | image = var.image 64 | sleep_time = "1000s" 65 | service_account = google_service_account.f5_bigip_user.email 66 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 67 | } 68 | 69 | -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy/output.tf: -------------------------------------------------------------------------------- 1 | output "bigip_password" { 2 | value = module.bigip.*.bigip_password 3 | } 4 | output "mgmtPublicIP" { 5 | value = module.bigip.*.mgmtPublicIP 6 | } 7 | output "bigip_username" { 8 | value = module.bigip.*.f5_username 9 | } 10 | output "mgmtPort" { 11 | value = module.bigip.*.mgmtPort 12 | } 13 | output "public_addresses" { 14 | value = module.bigip.*.public_addresses 15 | } 16 | output "private_addresses" { 17 | value = module.bigip.*.private_addresses 18 | } 19 | output "service_account" { 20 | value = module.bigip.*.service_account 21 | } 22 | output "bigip_instance_ids" { 23 | value = module.bigip.*.bigip_instance_ids 24 | } 25 | -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-central1" 2 | prefix = "tf-gcp-bigip" 3 | # image = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-3-3-0-0-3-payg-best-1gbps-221222233235" 4 | image = "projects/f5-7626-networks-public/global/images/f5-bigip-17-1-1-4-0-0-9-payg-best-plus-200mbps-240902171748" 5 | # f5-bigip-17-1-0-1-0-0-4-payg-best-plus-25mbps-230407103349" -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy/variables.tf: -------------------------------------------------------------------------------- 1 | variable "instance_count" { 2 | description = "Number of Bigip instances to create( From terraform 0.13, module supports count feature to spin mutliple instances )" 3 | type = number 4 | default = 1 5 | } 6 | variable "prefix" { 7 | description = "Prefix for resources created by this module" 8 | type = string 9 | default = "tf-gcp-bigip" 10 | } 11 | variable "project_id" { 12 | type = string 13 | description = "The GCP project identifier where the cluster will be created." 14 | } 15 | variable "region" { 16 | type = string 17 | description = "The compute region which will host the BIG-IP VMs" 18 | } 19 | variable "zone" { 20 | type = string 21 | default = "us-central1-a" 22 | description = "The compute zones which will host the BIG-IP VMs" 23 | } 24 | variable "image" { 25 | type = string 26 | # default = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-2-2-0-0-28-payg-best-plus-25mbps-220505080809" 27 | description = "The self-link URI for a BIG-IP image to use as a base for the VM cluster. This can be an official F5 image from GCP Marketplace, or a customised image." 28 | } 29 | 30 | variable "service_account" { 31 | description = "service account email to use with BIG-IP vms" 32 | type = string 33 | } 34 | 35 | -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_custom_runtime_init/custom_onboard_big.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -f /config/startup_finished ]; then 3 | exit 4 | fi 5 | if [ -f /config/first_run_flag ]; then 6 | echo "Skip first run steps, already ran." 7 | else 8 | /usr/bin/mkdir -p /var/log/cloud /config/cloud /var/lib/cloud/icontrollx_installs /var/config/rest/downloads 9 | LOG_FILE=/var/log/cloud/startup-script-pre-nic-swap.log 10 | /usr/bin/touch $LOG_FILE 11 | npipe=/tmp/$$.tmp 12 | /usr/bin/trap "rm -f $npipe" EXIT 13 | /usr/bin/mknod $npipe p 14 | /usr/bin/tee <$npipe -a $LOG_FILE /dev/ttyS0 & 15 | exec 1>&- 16 | exec 1>$npipe 17 | exec 2>&1 18 | cat << 'EOF' > /config/cloud/runtime-init-conf.yaml 19 | --- 20 | controls: 21 | extensionInstallDelayInMs: 60000 22 | runtime_parameters: 23 | - name: USER_NAME 24 | type: static 25 | value: ${bigip_username} 26 | - name: SSH_KEYS 27 | type: static 28 | value: "${ssh_keypair}" 29 | - name: HOST_NAME 30 | type: metadata 31 | metadataProvider: 32 | environment: gcp 33 | type: compute 34 | field: name 35 | EOF 36 | if ${gcp_secret_manager_authentication}; then 37 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 38 | - name: ADMIN_PASS 39 | type: secret 40 | secretProvider: 41 | environment: gcp 42 | type: SecretsManager 43 | version: latest 44 | secretId: ${bigip_password} 45 | pre_onboard_enabled: [] 46 | EOF 47 | else 48 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 49 | - name: ADMIN_PASS 50 | type: static 51 | value: ${bigip_password} 52 | pre_onboard_enabled: [] 53 | EOF 54 | fi 55 | cat /config/cloud/runtime-init-conf.yaml > /config/cloud/runtime-init-conf-backup.yaml 56 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 57 | extension_packages: 58 | install_operations: 59 | - extensionType: do 60 | extensionVersion: ${DO_VER} 61 | extensionUrl: ${DO_URL} 62 | - extensionType: as3 63 | extensionVersion: ${AS3_VER} 64 | extensionUrl: ${AS3_URL} 65 | - extensionType: ts 66 | extensionVersion: ${TS_VER} 67 | extensionUrl: ${TS_URL} 68 | - extensionType: cf 69 | extensionVersion: ${CFE_VER} 70 | extensionUrl: ${CFE_URL} 71 | - extensionType: fast 72 | extensionVersion: ${FAST_VER} 73 | extensionUrl: ${FAST_URL} 74 | extension_services: 75 | service_operations: 76 | - extensionType: do 77 | type: inline 78 | value: 79 | schemaVersion: 1.0.0 80 | class: Device 81 | async: true 82 | Common: 83 | class: Tenant 84 | hostname: '{{{HOST_NAME}}}.com' 85 | myNtp: 86 | class: NTP 87 | servers: 88 | - 169.254.169.254 89 | timezone: UTC 90 | myDns: 91 | class: DNS 92 | nameServers: 93 | - 169.254.169.254 94 | myProvisioning: 95 | class: Provision 96 | ltm: nominal 97 | admin: 98 | class: User 99 | partitionAccess: 100 | all-partitions: 101 | role: admin 102 | password: '{{{ADMIN_PASS}}}' 103 | shell: bash 104 | keys: 105 | - '{{{SSH_KEYS}}}' 106 | userType: regular 107 | '{{{USER_NAME}}}': 108 | class: User 109 | partitionAccess: 110 | all-partitions: 111 | role: admin 112 | password: '{{{ADMIN_PASS}}}' 113 | shell: bash 114 | keys: 115 | - '{{{SSH_KEYS}}}' 116 | userType: regular 117 | post_onboard_enabled: [] 118 | EOF 119 | cat << 'EOF' >> /config/cloud/runtime-init-conf-backup.yaml 120 | extension_services: 121 | service_operations: 122 | - extensionType: do 123 | type: inline 124 | value: 125 | schemaVersion: 1.0.0 126 | class: Device 127 | async: true 128 | Common: 129 | class: Tenant 130 | hostname: '{{{HOST_NAME}}}.com' 131 | myNtp: 132 | class: NTP 133 | servers: 134 | - 169.254.169.254 135 | timezone: UTC 136 | myDns: 137 | class: DNS 138 | nameServers: 139 | - 169.254.169.254 140 | myProvisioning: 141 | class: Provision 142 | ltm: nominal 143 | admin: 144 | class: User 145 | partitionAccess: 146 | all-partitions: 147 | role: admin 148 | password: '{{{ADMIN_PASS}}}' 149 | shell: bash 150 | keys: 151 | - '{{{SSH_KEYS}}}' 152 | userType: regular 153 | '{{{USER_NAME}}}': 154 | class: User 155 | partitionAccess: 156 | all-partitions: 157 | role: admin 158 | password: '{{{ADMIN_PASS}}}' 159 | shell: bash 160 | keys: 161 | - '{{{SSH_KEYS}}}' 162 | userType: regular 163 | post_onboard_enabled: [] 164 | EOF 165 | /usr/bin/cat << 'EOF' > /config/nic-swap.sh 166 | #!/bin/bash 167 | /usr/bin/touch /config/nic_swap_flag 168 | /usr/bin/setdb provision.managementeth eth1 169 | /usr/bin/setdb provision.extramb 1000 || true 170 | /usr/bin/setdb provision.restjavad.extramb 1384 || /usr/bin/setdb restjavad.useextramb true || true 171 | /usr/bin/setdb iapplxrpm.timeout 300 || true 172 | /usr/bin/setdb icrd.timeout 180 || true 173 | /usr/bin/setdb restjavad.timeout 180 || true 174 | /usr/bin/setdb restnoded.timeout 180 || true 175 | reboot 176 | EOF 177 | /usr/bin/cat << 'EOF' > /config/startup-script.sh 178 | #!/bin/bash 179 | LOG_FILE=/var/log/cloud/startup-script-post-swap-nic.log 180 | touch $LOG_FILE 181 | npipe=/tmp/$$.tmp 182 | /usr/bin/trap "rm -f $npipe" EXIT 183 | /usr/bin/mknod $npipe p 184 | /usr/bin/tee <$npipe -a $LOG_FILE /dev/ttyS0 & 185 | exec 1>&- 186 | exec 1>$npipe 187 | exec 2>&1 188 | if [[ ${NIC_COUNT} ]]; then 189 | # Need to remove existing and recreate a MGMT default route as not provided by DHCP on 2nd NIC Route name must be same as in DO config. 190 | source /usr/lib/bigstart/bigip-ready-functions 191 | wait_bigip_ready 192 | tmsh modify sys global-settings mgmt-dhcp disabled 193 | tmsh delete sys management-route all 194 | tmsh delete sys management-ip all 195 | wait_bigip_ready 196 | # Wait until a little more until dhcp/chmand is finished re-configuring MGMT IP w/ "chmand[4267]: 012a0003:3: Mgmt Operation:0 Dest:0.0.0.0" 197 | sleep 15 198 | MGMT_GW=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | grep -oE '[^ ]+$' | tr -d ';') 199 | SELF_IP_MGMT=$(egrep fixed-address /var/lib/dhclient/dhclient.leases | tail -1 | grep -oE '[^ ]+$' | tr -d ';') 200 | MGMT_BITMASK=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | cut -d ',' -f 2 | cut -d ' ' -f 1 | cut -d '.' -f 1) 201 | MGMT_NETWORK=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | cut -d ',' -f 2 | cut -d ' ' -f 1 | cut -d '.' -f 2-4).0 202 | echo "MGMT_GW - " 203 | echo $MGMT_GW 204 | echo "SELF_IP_MGMT - " 205 | echo $SELF_IP_MGMT 206 | echo "MGMT_BITMASK - " 207 | echo $MGMT_BITMASK 208 | echo "MGMT_NETWORK - " 209 | echo $MGMT_NETWORK 210 | tmsh create sys management-ip $SELF_IP_MGMT/32 211 | echo "tmsh list sys management-ip - " 212 | tmsh list sys management-ip 213 | tmsh create sys management-route mgmt_gw network $MGMT_GW/32 type interface 214 | tmsh create sys management-route mgmt_net network $MGMT_NETWORK/$MGMT_BITMASK gateway $MGMT_GW 215 | tmsh create sys management-route defaultManagementRoute network default gateway $MGMT_GW mtu 1460 216 | echo "tmsh list sys management-route - " 217 | tmsh list sys management-route 218 | tmsh modify sys global-settings remote-host add { metadata.google.internal { hostname metadata.google.internal addr 169.254.169.254 } } 219 | tmsh save /sys config 220 | fi 221 | /usr/bin/touch /config/startup_finished 222 | EOF 223 | /usr/bin/chmod +x /config/nic-swap.sh 224 | /usr/bin/chmod +x /config/startup-script.sh 225 | MULTI_NIC="${NIC_COUNT}" 226 | /usr/bin/touch /config/first_run_flag 227 | fi 228 | if [[ $MULTI_NIC == "true" ]]; then 229 | nohup /config/nic-swap.sh & 230 | else 231 | /usr/bin/touch /config/nic_swap_flag 232 | fi 233 | if [ -f /config/nic_swap_flag ]; then 234 | nohup /config/startup-script.sh & 235 | fi -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_custom_runtime_init/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | } 4 | provider "google" { 5 | project = var.project_id 6 | region = var.region 7 | zone = var.zone 8 | } 9 | 10 | # Create a random id 11 | # 12 | resource "random_id" "id" { 13 | byte_length = 2 14 | } 15 | 16 | # Create random password for BIG-IP 17 | # 18 | resource "random_string" "password" { 19 | length = 16 20 | min_upper = 1 21 | min_lower = 1 22 | min_numeric = 1 23 | special = false 24 | } 25 | resource "google_compute_network" "mgmtvpc" { 26 | name = format("%s-mgmtvpc-%s", var.prefix, random_id.id.hex) 27 | auto_create_subnetworks = false 28 | } 29 | resource "google_compute_network" "extvpc" { 30 | name = format("%s-extvpc-%s", var.prefix, random_id.id.hex) 31 | auto_create_subnetworks = false 32 | } 33 | resource "google_compute_network" "intvpc" { 34 | name = format("%s-intvpc-%s", var.prefix, random_id.id.hex) 35 | auto_create_subnetworks = false 36 | } 37 | resource "google_compute_subnetwork" "mgmt_subnetwork" { 38 | name = format("%s-mgmt-%s", var.prefix, random_id.id.hex) 39 | ip_cidr_range = "10.0.1.0/24" 40 | region = var.region 41 | network = google_compute_network.mgmtvpc.id 42 | } 43 | resource "google_compute_subnetwork" "external_subnetwork" { 44 | name = format("%s-ext-%s", var.prefix, random_id.id.hex) 45 | ip_cidr_range = "10.0.2.0/24" 46 | region = var.region 47 | network = google_compute_network.extvpc.id 48 | } 49 | 50 | resource "google_compute_subnetwork" "internal_subnetwork" { 51 | name = format("%s-int-%s", var.prefix, random_id.id.hex) 52 | ip_cidr_range = "10.0.3.0/24" 53 | region = var.region 54 | network = google_compute_network.intvpc.id 55 | } 56 | 57 | resource "google_compute_firewall" "mgmt_firewall" { 58 | name = format("%s-mgmt-firewall-%s", var.prefix, random_id.id.hex) 59 | network = google_compute_network.mgmtvpc.id 60 | allow { 61 | protocol = "tcp" 62 | ports = ["22", "80", "443", "8443"] 63 | } 64 | allow { 65 | protocol = "icmp" 66 | } 67 | source_ranges = ["0.0.0.0/0"] 68 | } 69 | resource "google_compute_firewall" "ext_firewall" { 70 | name = format("%s-ext-firewall-%s", var.prefix, random_id.id.hex) 71 | network = google_compute_network.extvpc.id 72 | allow { 73 | protocol = "tcp" 74 | ports = ["22", "80", "443", "8443"] 75 | } 76 | allow { 77 | protocol = "icmp" 78 | } 79 | source_ranges = ["0.0.0.0/0"] 80 | } 81 | 82 | 83 | module "bigip" { 84 | count = var.instance_count 85 | source = "../.." 86 | prefix = format("%s-3nic", var.prefix) 87 | project_id = var.project_id 88 | zone = var.zone 89 | image = var.image 90 | service_account = var.service_account 91 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = false, "private_ip_primary" = "" }] 92 | external_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = false, "private_ip_primary" = "", "private_ip_secondary" = "" }] 93 | internal_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.internal_subnetwork.id, "public_ip" = false, "private_ip_primary" = "", "private_ip_secondary" = "" }] 94 | custom_user_data = templatefile("custom_onboard_big.tpl", 95 | { 96 | onboard_log = var.onboard_log 97 | libs_dir = var.libs_dir 98 | bigip_username = var.f5_username 99 | gcp_secret_manager_authentication = var.gcp_secret_manager_authentication 100 | bigip_password = (var.f5_password == "") ? (var.gcp_secret_manager_authentication ? var.gcp_secret_name : random_string.password.result) : var.f5_password 101 | ssh_keypair = file(var.f5_ssh_publickey) 102 | INIT_URL = var.INIT_URL, 103 | DO_URL = var.DO_URL, 104 | DO_VER = format("v%s", split("-", split("/", var.DO_URL)[length(split("/", var.DO_URL)) - 1])[3]) 105 | AS3_URL = var.AS3_URL, 106 | AS3_VER = format("v%s", split("-", split("/", var.AS3_URL)[length(split("/", var.AS3_URL)) - 1])[2]) 107 | TS_VER = format("v%s", split("-", split("/", var.TS_URL)[length(split("/", var.TS_URL)) - 1])[2]) 108 | TS_URL = var.TS_URL, 109 | CFE_VER = format("v%s", split("-", split("/", var.CFE_URL)[length(split("/", var.CFE_URL)) - 1])[3]) 110 | CFE_URL = var.CFE_URL, 111 | FAST_URL = var.FAST_URL 112 | FAST_VER = format("v%s", split("-", split("/", var.FAST_URL)[length(split("/", var.FAST_URL)) - 1])[3]) 113 | NIC_COUNT = true 114 | }) 115 | } -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_custom_runtime_init/output.tf: -------------------------------------------------------------------------------- 1 | output "bigip_password" { 2 | value = module.bigip.*.bigip_password 3 | } 4 | output "mgmtPublicIP" { 5 | value = module.bigip.*.mgmtPublicIP 6 | } 7 | output "bigip_username" { 8 | value = module.bigip.*.f5_username 9 | } 10 | output "mgmtPort" { 11 | value = module.bigip.*.mgmtPort 12 | } 13 | output "public_addresses" { 14 | value = module.bigip.*.public_addresses 15 | } 16 | output "private_addresses" { 17 | value = module.bigip.*.private_addresses 18 | } 19 | output "service_account" { 20 | value = module.bigip.*.service_account 21 | } 22 | -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_custom_runtime_init/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-central1" 2 | prefix = "tf-gcp-bigip" -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_custom_runtime_init/variables.tf: -------------------------------------------------------------------------------- 1 | variable "instance_count" { 2 | description = "Number of Bigip instances to create( From terraform 0.13, module supports count feature to spin mutliple instances )" 3 | type = number 4 | default = 1 5 | } 6 | variable "prefix" { 7 | description = "Prefix for resources created by this module" 8 | type = string 9 | default = "tf-gcp-bigip" 10 | } 11 | variable "project_id" { 12 | type = string 13 | description = "The GCP project identifier where the cluster will be created." 14 | } 15 | variable "region" { 16 | type = string 17 | description = "The compute region which will host the BIG-IP VMs" 18 | } 19 | variable "zone" { 20 | type = string 21 | default = "us-central1-a" 22 | description = "The compute zones which will host the BIG-IP VMs" 23 | } 24 | variable "image" { 25 | type = string 26 | default = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-2-2-0-0-28-payg-best-plus-25mbps-220505080809" 27 | description = "The self-link URI for a BIG-IP image to use as a base for the VM cluster. This can be an official F5 image from GCP Marketplace, or a customised image." 28 | } 29 | 30 | variable "service_account" { 31 | description = "service account email to use with BIG-IP vms" 32 | type = string 33 | } 34 | 35 | variable "f5_username" { 36 | description = "The admin username of the F5 Bigip that will be deployed" 37 | default = "bigipuser" 38 | } 39 | 40 | variable "f5_password" { 41 | description = "The admin password of the F5 Bigip that will be deployed" 42 | default = "" 43 | } 44 | 45 | variable "onboard_log" { 46 | description = "Directory on the BIG-IP to store the cloud-init logs" 47 | default = "/var/log/startup-script.log" 48 | type = string 49 | } 50 | 51 | variable "libs_dir" { 52 | description = "Directory on the BIG-IP to download the A&O Toolchain into" 53 | default = "/config/cloud/gcp/node_modules" 54 | type = string 55 | } 56 | 57 | variable "gcp_secret_manager_authentication" { 58 | description = "Whether to use secret manager to pass authentication" 59 | type = bool 60 | default = false 61 | } 62 | 63 | variable "gcp_secret_name" { 64 | description = "The secret to get the secret version for" 65 | type = string 66 | default = "" 67 | } 68 | 69 | variable "gcp_secret_version" { 70 | description = "(Optional)The version of the secret to get. If it is not provided, the latest version is retrieved." 71 | type = string 72 | default = "latest" 73 | } 74 | 75 | ## Please check and update the latest DO URL from https://github.com/F5Networks/f5-declarative-onboarding/releases 76 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 77 | variable "DO_URL" { 78 | description = "URL to download the BIG-IP Declarative Onboarding module" 79 | type = string 80 | default = "https://github.com/F5Networks/f5-declarative-onboarding/releases/download/v1.42.0/f5-declarative-onboarding-1.42.0-9.noarch.rpm" 81 | } 82 | ## Please check and update the latest AS3 URL from https://github.com/F5Networks/f5-appsvcs-extension/releases/latest 83 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 84 | variable "AS3_URL" { 85 | description = "URL to download the BIG-IP Application Service Extension 3 (AS3) module" 86 | type = string 87 | default = "https://github.com/F5Networks/f5-appsvcs-extension/releases/download/v3.49.0/f5-appsvcs-3.49.0-6.noarch.rpm" 88 | } 89 | 90 | ## Please check and update the latest TS URL from https://github.com/F5Networks/f5-telemetry-streaming/releases/latest 91 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 92 | variable "TS_URL" { 93 | description = "URL to download the BIG-IP Telemetry Streaming module" 94 | type = string 95 | default = "https://github.com/F5Networks/f5-telemetry-streaming/releases/download/v1.34.0/f5-telemetry-1.34.0-1.noarch.rpm" 96 | } 97 | 98 | ## Please check and update the latest Failover Extension URL from https://github.com/F5Networks/f5-cloud-failover-extension/releases/latest 99 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 100 | variable "CFE_URL" { 101 | description = "URL to download the BIG-IP Cloud Failover Extension module" 102 | type = string 103 | default = "https://github.com/F5Networks/f5-cloud-failover-extension/releases/download/v2.0.2/f5-cloud-failover-2.0.2-2.noarch.rpm" 104 | } 105 | 106 | ## Please check and update the latest FAST URL from https://github.com/F5Networks/f5-appsvcs-templates/releases/latest 107 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 108 | variable "FAST_URL" { 109 | description = "URL to download the BIG-IP FAST module" 110 | type = string 111 | default = "https://github.com/F5Networks/f5-appsvcs-templates/releases/download/v1.25.0/f5-appsvcs-templates-1.25.0-1.noarch.rpm" 112 | } 113 | ## Please check and update the latest runtime init URL from https://github.com/F5Networks/f5-bigip-runtime-init/releases/latest 114 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 115 | variable "INIT_URL" { 116 | description = "URL to download the BIG-IP runtime init" 117 | type = string 118 | default = "https://cdn.f5.com/product/cloudsolutions/f5-bigip-runtime-init/v2.0.1/dist/f5-bigip-runtime-init-2.0.1-1.gz.run" 119 | } 120 | 121 | variable "labels" { 122 | description = "An optional map of key:value labels to add to the instance" 123 | type = map(string) 124 | default = {} 125 | } 126 | 127 | variable "f5_ssh_publickey" { 128 | description = "Path to the public key to be used for ssh access to the VM. Only used with non-Windows vms and can be left as-is even if using Windows vms. If specifying a path to a certification on a Windows machine to provision a linux vm use the / in the path versus backslash. e.g. c:/home/id_rsa.pub" 129 | default = "~/.ssh/id_rsa.pub" 130 | } -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_provider_integration/bigip.tf: -------------------------------------------------------------------------------- 1 | 2 | terraform { 3 | required_providers { 4 | bigip = { 5 | source = "F5Networks/bigip" 6 | version = "1.16.1" 7 | } 8 | } 9 | } 10 | 11 | provider "bigip" { 12 | # Configuration options 13 | address = format("https://%s:%s", module.bigip.*.mgmtPublicIP[0], module.bigip.*.mgmtPort[0]) 14 | username = module.bigip.*.f5_username[0] 15 | password = module.bigip.*.bigip_password[0] 16 | } 17 | 18 | resource "bigip_ltm_profile_http" "f5vm02-rechunk-http" { 19 | name = "/Common/rechunk-http" 20 | defaults_from = "/Common/http" 21 | response_chunking = "rechunk" 22 | } 23 | 24 | # A Virtual server with separate client and server profiles 25 | resource "bigip_ltm_virtual_server" "https" { 26 | name = "/Common/vs_github_test_443" 27 | destination = "10.255.255.254" 28 | description = "VirtualServer-test" 29 | port = 443 30 | profiles = ["/Common/tcp", bigip_ltm_profile_http.f5vm02-rechunk-http.name] 31 | client_profiles = ["/Common/clientssl"] 32 | server_profiles = ["/Common/serverssl"] 33 | security_log_profiles = ["/Common/global-network"] 34 | source_address_translation = "automap" 35 | } 36 | -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_provider_integration/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | } 4 | 5 | provider "google" { 6 | project = var.project_id 7 | region = var.region 8 | zone = var.zone 9 | } 10 | 11 | # Create a random id 12 | # 13 | resource "random_id" "id" { 14 | byte_length = 2 15 | } 16 | 17 | # Create random password for BIG-IP 18 | # 19 | resource "random_string" "password" { 20 | length = 16 21 | min_upper = 1 22 | min_lower = 1 23 | min_numeric = 1 24 | special = false 25 | } 26 | 27 | resource "google_compute_network" "vpc" { 28 | name = format("%s-vpc-%s", var.prefix, random_id.id.hex) 29 | auto_create_subnetworks = false 30 | } 31 | 32 | resource "google_compute_subnetwork" "mgmt_subnetwork" { 33 | name = format("%s-mgmt-%s", var.prefix, random_id.id.hex) 34 | ip_cidr_range = "10.0.0.0/16" 35 | region = var.region 36 | network = google_compute_network.vpc.id 37 | } 38 | 39 | resource "google_compute_firewall" "mgmt_firewall" { 40 | name = format("%s-mgmt-firewall-%s", var.prefix, random_id.id.hex) 41 | network = google_compute_network.vpc.id 42 | allow { 43 | protocol = "tcp" 44 | ports = ["22", "80", "443", "8443"] 45 | } 46 | allow { 47 | protocol = "icmp" 48 | } 49 | source_ranges = ["0.0.0.0/0"] 50 | } 51 | 52 | resource "google_service_account" "f5_bigip_user" { 53 | account_id = "f5-bigip-user" 54 | description = "User for F5 BIGIP" 55 | } 56 | 57 | module "bigip" { 58 | count = var.instance_count 59 | source = "../.." 60 | prefix = format("%s-1nic", var.prefix) 61 | project_id = var.project_id 62 | zone = var.zone 63 | image = var.image 64 | sleep_time = "1800s" 65 | service_account = google_service_account.f5_bigip_user.email 66 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 67 | } 68 | 69 | -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_provider_integration/output.tf: -------------------------------------------------------------------------------- 1 | output "bigip_password" { 2 | value = module.bigip.*.bigip_password 3 | } 4 | output "mgmtPublicIP" { 5 | value = module.bigip.*.mgmtPublicIP 6 | } 7 | output "bigip_username" { 8 | value = module.bigip.*.f5_username 9 | } 10 | output "mgmtPort" { 11 | value = module.bigip.*.mgmtPort 12 | } 13 | output "public_addresses" { 14 | value = module.bigip.*.public_addresses 15 | } 16 | output "private_addresses" { 17 | value = module.bigip.*.private_addresses 18 | } 19 | output "service_account" { 20 | value = module.bigip.*.service_account 21 | } 22 | output "bigip_instance_ids" { 23 | value = module.bigip.*.bigip_instance_ids 24 | } 25 | -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_provider_integration/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-central1" 2 | prefix = "tf-gcp-bigip" 3 | # image = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-3-1-0-0-11-payg-best-plus-25mbps-220721054250" 4 | image = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-3-3-0-0-3-payg-best-1gbps-221222233235" 5 | # image = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-3-2-0-0-4-byol-all-modules-2boot-loc-20914235403" -------------------------------------------------------------------------------- /examples/bigip_gcp_1nic_deploy_provider_integration/variables.tf: -------------------------------------------------------------------------------- 1 | variable "instance_count" { 2 | description = "Number of Bigip instances to create( From terraform 0.13, module supports count feature to spin mutliple instances )" 3 | type = number 4 | default = 1 5 | } 6 | variable "prefix" { 7 | description = "Prefix for resources created by this module" 8 | type = string 9 | default = "tf-gcp-bigip" 10 | } 11 | variable "project_id" { 12 | type = string 13 | description = "The GCP project identifier where the cluster will be created." 14 | } 15 | variable "region" { 16 | type = string 17 | description = "The compute region which will host the BIG-IP VMs" 18 | } 19 | variable "zone" { 20 | type = string 21 | default = "us-central1-a" 22 | description = "The compute zones which will host the BIG-IP VMs" 23 | } 24 | variable "image" { 25 | type = string 26 | # default = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-2-2-0-0-28-payg-best-plus-25mbps-220505080809" 27 | description = "The self-link URI for a BIG-IP image to use as a base for the VM cluster. This can be an official F5 image from GCP Marketplace, or a customised image." 28 | } 29 | 30 | variable "service_account" { 31 | description = "service account email to use with BIG-IP vms" 32 | type = string 33 | } 34 | 35 | -------------------------------------------------------------------------------- /examples/bigip_gcp_2nic_deploy/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | } 4 | provider "google" { 5 | project = var.project_id 6 | region = var.region 7 | zone = var.zone 8 | } 9 | # Create a random id 10 | # 11 | resource "random_id" "id" { 12 | byte_length = 2 13 | } 14 | 15 | # Create random password for BIG-IP 16 | # 17 | resource "random_string" "password" { 18 | length = 16 19 | min_upper = 1 20 | min_lower = 1 21 | min_numeric = 1 22 | special = false 23 | } 24 | 25 | resource "google_compute_network" "mgmtvpc" { 26 | name = format("%s-mgmtvpc-%s", var.prefix, random_id.id.hex) 27 | auto_create_subnetworks = false 28 | } 29 | resource "google_compute_network" "extvpc" { 30 | name = format("%s-extvpc-%s", var.prefix, random_id.id.hex) 31 | auto_create_subnetworks = false 32 | } 33 | 34 | resource "google_compute_network" "extvpc2" { 35 | name = format("%s-extvpc2-%s", var.prefix, random_id.id.hex) 36 | auto_create_subnetworks = false 37 | } 38 | 39 | resource "google_compute_subnetwork" "mgmt_subnetwork" { 40 | name = format("%s-mgmt-%s", var.prefix, random_id.id.hex) 41 | ip_cidr_range = "10.0.0.0/24" 42 | region = var.region 43 | network = google_compute_network.mgmtvpc.id 44 | } 45 | resource "google_compute_subnetwork" "external_subnetwork" { 46 | name = format("%s-ext-%s", var.prefix, random_id.id.hex) 47 | ip_cidr_range = "10.0.1.0/24" 48 | region = var.region 49 | network = google_compute_network.extvpc.id 50 | } 51 | 52 | resource "google_compute_subnetwork" "external_subnetwork2" { 53 | name = format("%s-ext2-%s", var.prefix, random_id.id.hex) 54 | ip_cidr_range = "10.0.2.0/24" 55 | region = var.region 56 | network = google_compute_network.extvpc2.id 57 | } 58 | 59 | resource "google_compute_firewall" "mgmt_firewall" { 60 | name = format("%s-mgmt-firewall-%s", var.prefix, random_id.id.hex) 61 | network = google_compute_network.mgmtvpc.id 62 | allow { 63 | protocol = "tcp" 64 | ports = ["22", "80", "443", "8443"] 65 | } 66 | allow { 67 | protocol = "icmp" 68 | } 69 | source_ranges = ["0.0.0.0/0"] 70 | } 71 | resource "google_compute_firewall" "ext_firewall" { 72 | name = format("%s-ext-firewall-%s", var.prefix, random_id.id.hex) 73 | network = google_compute_network.extvpc.id 74 | allow { 75 | protocol = "tcp" 76 | ports = ["22", "80", "443", "8443"] 77 | } 78 | allow { 79 | protocol = "icmp" 80 | } 81 | source_ranges = ["0.0.0.0/0"] 82 | } 83 | module "bigip" { 84 | count = var.instance_count 85 | source = "../.." 86 | prefix = format("%s-2nic", var.prefix) 87 | project_id = var.project_id 88 | zone = var.zone 89 | image = var.image 90 | service_account = var.service_account 91 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 92 | external_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = true, "private_ip_primary" = "", "private_ip_secondary" = "" }] 93 | } 94 | -------------------------------------------------------------------------------- /examples/bigip_gcp_2nic_deploy/output.tf: -------------------------------------------------------------------------------- 1 | output "bigip_password" { 2 | value = module.bigip.*.bigip_password 3 | } 4 | output "mgmtPublicIP" { 5 | value = module.bigip.*.mgmtPublicIP 6 | } 7 | output "bigip_username" { 8 | value = module.bigip.*.f5_username 9 | } 10 | output "mgmtPort" { 11 | value = module.bigip.*.mgmtPort 12 | } 13 | output "public_addresses" { 14 | value = module.bigip.*.public_addresses 15 | } 16 | output "private_addresses" { 17 | value = module.bigip.*.private_addresses 18 | } 19 | output "service_account" { 20 | value = module.bigip.*.service_account 21 | } 22 | output "bigip_instance_ids" { 23 | value = module.bigip.*.bigip_instance_ids 24 | } 25 | -------------------------------------------------------------------------------- /examples/bigip_gcp_2nic_deploy/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-central1" 2 | prefix = "tf-gcp-bigip" -------------------------------------------------------------------------------- /examples/bigip_gcp_2nic_deploy/variables.tf: -------------------------------------------------------------------------------- 1 | variable "instance_count" { 2 | description = "Number of Bigip instances to create( From terraform 0.13, module supports count feature to spin mutliple instances )" 3 | type = number 4 | default = 1 5 | } 6 | variable "prefix" { 7 | description = "Prefix for resources created by this module" 8 | type = string 9 | default = "tf-gcp-bigip" 10 | } 11 | variable "project_id" { 12 | type = string 13 | description = "The GCP project identifier where the cluster will be created." 14 | } 15 | variable "region" { 16 | type = string 17 | description = "The compute region which will host the BIG-IP VMs" 18 | } 19 | variable "zone" { 20 | type = string 21 | default = "us-central1-a" 22 | description = "The compute zones which will host the BIG-IP VMs" 23 | } 24 | variable "image" { 25 | type = string 26 | default = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-2-2-0-0-28-payg-best-plus-25mbps-220505080809" 27 | description = "The self-link URI for a BIG-IP image to use as a base for the VM cluster.This can be an official F5 image from GCP Marketplace, or a customised image." 28 | } 29 | 30 | variable "service_account" { 31 | description = "service account email to use with BIG-IP vms" 32 | type = string 33 | } 34 | -------------------------------------------------------------------------------- /examples/bigip_gcp_3nic_deploy/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | } 4 | provider "google" { 5 | project = var.project_id 6 | region = var.region 7 | zone = var.zone 8 | } 9 | 10 | # Create a random id 11 | # 12 | resource "random_id" "id" { 13 | byte_length = 2 14 | } 15 | 16 | # Create random password for BIG-IP 17 | # 18 | resource "random_string" "password" { 19 | length = 16 20 | min_upper = 1 21 | min_lower = 1 22 | min_numeric = 1 23 | special = false 24 | } 25 | resource "google_compute_network" "mgmtvpc" { 26 | name = format("%s-mgmtvpc-%s", var.prefix, random_id.id.hex) 27 | auto_create_subnetworks = false 28 | } 29 | resource "google_compute_network" "extvpc" { 30 | name = format("%s-extvpc-%s", var.prefix, random_id.id.hex) 31 | auto_create_subnetworks = false 32 | } 33 | resource "google_compute_network" "intvpc" { 34 | name = format("%s-intvpc-%s", var.prefix, random_id.id.hex) 35 | auto_create_subnetworks = false 36 | } 37 | resource "google_compute_subnetwork" "mgmt_subnetwork" { 38 | name = format("%s-mgmt-%s", var.prefix, random_id.id.hex) 39 | ip_cidr_range = "10.0.1.0/24" 40 | region = var.region 41 | network = google_compute_network.mgmtvpc.id 42 | } 43 | resource "google_compute_subnetwork" "external_subnetwork" { 44 | name = format("%s-ext-%s", var.prefix, random_id.id.hex) 45 | ip_cidr_range = "10.0.2.0/24" 46 | region = var.region 47 | network = google_compute_network.extvpc.id 48 | } 49 | 50 | resource "google_compute_subnetwork" "internal_subnetwork" { 51 | name = format("%s-int-%s", var.prefix, random_id.id.hex) 52 | ip_cidr_range = "10.0.3.0/24" 53 | region = var.region 54 | network = google_compute_network.intvpc.id 55 | } 56 | 57 | resource "google_compute_firewall" "mgmt_firewall" { 58 | name = format("%s-mgmt-firewall-%s", var.prefix, random_id.id.hex) 59 | network = google_compute_network.mgmtvpc.id 60 | allow { 61 | protocol = "tcp" 62 | ports = ["22", "80", "443", "8443"] 63 | } 64 | allow { 65 | protocol = "icmp" 66 | } 67 | source_ranges = ["0.0.0.0/0"] 68 | } 69 | 70 | resource "google_compute_firewall" "ext_firewall" { 71 | name = format("%s-ext-firewall-%s", var.prefix, random_id.id.hex) 72 | network = google_compute_network.extvpc.id 73 | allow { 74 | protocol = "tcp" 75 | ports = ["22", "80", "443", "8443"] 76 | } 77 | allow { 78 | protocol = "icmp" 79 | } 80 | source_ranges = ["0.0.0.0/0"] 81 | } 82 | 83 | resource "google_compute_firewall" "int_firewall" { 84 | name = format("%s-intvpc-firewall-%s", var.prefix, random_id.id.hex) 85 | network = google_compute_network.intvpc.id 86 | allow { 87 | protocol = "tcp" 88 | ports = ["22", "80", "443", "8443"] 89 | } 90 | allow { 91 | protocol = "icmp" 92 | } 93 | source_ranges = ["0.0.0.0/0"] 94 | } 95 | 96 | resource "google_compute_firewall" "int_firewall_egress" { 97 | name = format("%s-intvpc-firewall-egress-%s", var.prefix, random_id.id.hex) 98 | network = google_compute_network.intvpc.id 99 | allow { 100 | protocol = "tcp" 101 | ports = ["22", "80", "443", "8443"] 102 | } 103 | direction = "EGRESS" 104 | allow { 105 | protocol = "icmp" 106 | } 107 | source_ranges = ["0.0.0.0/0"] 108 | } 109 | 110 | # metadata_startup_script = replace(coalesce(var.custom_user_data, templatefile("${path.module}/startup-script.tpl", 111 | # { 112 | # onboard_log = var.onboard_log 113 | # libs_dir = var.libs_dir 114 | # bigip_username = var.f5_username 115 | # gcp_secret_manager_authentication = var.gcp_secret_manager_authentication 116 | # bigip_password = (var.f5_password == "") ? (var.gcp_secret_manager_authentication ? var.gcp_secret_name : random_string.password.result) : var.f5_password 117 | # ssh_keypair = file(var.f5_ssh_publickey) 118 | # INIT_URL = var.INIT_URL, 119 | # DO_URL = var.DO_URL, 120 | # DO_VER = format("v%s", split("-", split("/", var.DO_URL)[length(split("/", var.DO_URL)) - 1])[3]) 121 | # AS3_URL = var.AS3_URL, 122 | # AS3_VER = format("v%s", split("-", split("/", var.AS3_URL)[length(split("/", var.AS3_URL)) - 1])[2]) 123 | # TS_VER = format("v%s", split("-", split("/", var.TS_URL)[length(split("/", var.TS_URL)) - 1])[2]) 124 | # TS_URL = var.TS_URL, 125 | # CFE_VER = format("v%s", split("-", split("/", var.CFE_URL)[length(split("/", var.CFE_URL)) - 1])[3]) 126 | # CFE_URL = var.CFE_URL, 127 | # FAST_URL = var.FAST_URL 128 | # FAST_VER = format("v%s", split("-", split("/", var.FAST_URL)[length(split("/", var.FAST_URL)) - 1])[3]) 129 | # NIC_COUNT = local.multiple_nic_count > 0 ? true : false 130 | # })), "/\r/", "") 131 | 132 | # # Setup Onboarding scripts 133 | # locals { 134 | # f5_onboard1 = templatefile("${path.module}/f5_onboard.tmpl", { 135 | # f5_username = var.f5_username 136 | # f5_password = var.gcp_secret_manager_authentication ? "" : var.f5_password 137 | # gcp_secret_manager_authentication = var.gcp_secret_manager_authentication 138 | # gcp_secret_name = var.gcp_secret_manager_authentication ? var.gcp_secret_name : "" 139 | # gcp_secret_version = var.gcp_secret_manager_authentication ? var.gcp_secret_version : "" 140 | # ssh_keypair = file(var.ssh_key) 141 | # gcp_project_id = var.gcp_project_id 142 | # INIT_URL = var.INIT_URL 143 | # DO_URL = var.DO_URL 144 | # AS3_URL = var.AS3_URL 145 | # TS_URL = var.TS_URL 146 | # FAST_URL = var.FAST_URL 147 | # DO_VER = split("/", var.DO_URL)[7] 148 | # AS3_VER = split("/", var.AS3_URL)[7] 149 | # TS_VER = split("/", var.TS_URL)[7] 150 | # FAST_VER = split("/", var.FAST_URL)[7] 151 | # dns_server = var.dns_server 152 | # dns_suffix = var.dns_suffix 153 | # ntp_server = var.ntp_server 154 | # timezone = var.timezone 155 | # bigIqLicenseType = var.bigIqLicenseType 156 | # bigIqHost = var.bigIqHost 157 | # bigIqPassword = var.bigIqPassword 158 | # bigIqUsername = var.bigIqUsername 159 | # bigIqLicensePool = var.bigIqLicensePool 160 | # bigIqSkuKeyword1 = var.bigIqSkuKeyword1 161 | # bigIqSkuKeyword2 = var.bigIqSkuKeyword2 162 | # bigIqUnitOfMeasure = var.bigIqUnitOfMeasure 163 | # bigIqHypervisor = var.bigIqHypervisor 164 | # NIC_COUNT = true 165 | # # public_vip = google_compute_address.vip1.address 166 | # }) 167 | # } 168 | 169 | module "bigip" { 170 | count = var.instance_count 171 | source = "../.." 172 | prefix = format("%s-3nic", var.prefix) 173 | project_id = var.project_id 174 | zone = var.zone 175 | image = var.image 176 | service_account = var.service_account 177 | sleep_time = "300s" 178 | machine_type = "n2-highmem-4" 179 | min_cpu_platform = "Intel Cascade Lake" # Add this line 180 | disk_type = "pd-ssd" 181 | # custom_user_data = local.f5_onboard1 182 | disk_size_gb = 120 # Minimum for multi-module provisioning 183 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 184 | external_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = false, "private_ip_primary" = "", "private_ip_secondary" = "" }] 185 | internal_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.internal_subnetwork.id, "public_ip" = false, "private_ip_primary" = "", "private_ip_secondary" = "" }] 186 | } 187 | 188 | # Create VM 189 | resource "google_compute_instance" "vm_instance_public" { 190 | name = format("%s-ubuntuvm01-%s", var.prefix, random_id.id.hex) 191 | machine_type = "n2-standard-2" 192 | zone = var.zone 193 | hostname = format("%s-ubuntuvm01-%s.com", var.prefix, random_id.id.hex) 194 | tags = ["ssh", "http"] 195 | boot_disk { 196 | initialize_params { 197 | image = "ubuntu-os-cloud/ubuntu-2004-lts" 198 | } 199 | } 200 | metadata_startup_script = templatefile("ubunturun.sh", {}) 201 | network_interface { 202 | subnetwork = google_compute_subnetwork.mgmt_subnetwork.id 203 | access_config {} 204 | } 205 | network_interface { 206 | subnetwork = google_compute_subnetwork.internal_subnetwork.id 207 | 208 | # access_config { } 209 | } 210 | metadata = merge(var.metadata, coalesce(var.f5_ssh_publickey, "unspecified") != "unspecified" ? { 211 | sshKeys = file(var.f5_ssh_publickey) 212 | } : {} 213 | ) 214 | } 215 | -------------------------------------------------------------------------------- /examples/bigip_gcp_3nic_deploy/output.tf: -------------------------------------------------------------------------------- 1 | output "bigip_password" { 2 | value = module.bigip.*.bigip_password 3 | } 4 | output "mgmtPublicIP" { 5 | value = module.bigip.*.mgmtPublicIP 6 | } 7 | output "bigip_username" { 8 | value = module.bigip.*.f5_username 9 | } 10 | output "mgmtPort" { 11 | value = module.bigip.*.mgmtPort 12 | } 13 | output "public_addresses" { 14 | value = module.bigip.*.public_addresses 15 | } 16 | output "private_addresses" { 17 | value = module.bigip.*.private_addresses 18 | } 19 | output "service_account" { 20 | value = module.bigip.*.service_account 21 | } 22 | output "self_link" { 23 | value = module.bigip.*.self_link 24 | } 25 | output "name" { 26 | value = module.bigip.*.name 27 | } 28 | output "zone" { 29 | value = module.bigip.*.zone 30 | } 31 | output "bigip_instance_ids" { 32 | value = module.bigip.*.bigip_instance_ids 33 | } 34 | -------------------------------------------------------------------------------- /examples/bigip_gcp_3nic_deploy/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-central1" 2 | prefix = "tf-gcp-bigip" 3 | image = "projects/f5-7626-networks-public/global/images/f5-bigip-17-1-2-0-0-8-payg-better-25mbps-241121080429" 4 | # f5-bigip-17-1-1-4-0-0-9-payg-best-plus-200mbps-240902171748" 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/bigip_gcp_3nic_deploy/ubunturun.sh: -------------------------------------------------------------------------------- 1 | sudo apt-get update; 2 | sudo apt-get install -yq build-essential apache2; 3 | sudo systemctl start apache2; 4 | sudo systemctl enable apache2; -------------------------------------------------------------------------------- /examples/bigip_gcp_3nic_deploy/variables.tf: -------------------------------------------------------------------------------- 1 | variable "instance_count" { 2 | description = "Number of Bigip instances to create( From terraform 0.13, module supports count feature to spin mutliple instances )" 3 | type = number 4 | default = 1 5 | } 6 | 7 | variable "prefix" { 8 | description = "Prefix for resources created by this module" 9 | type = string 10 | default = "tf-gcp-bigip" 11 | } 12 | variable "project_id" { 13 | type = string 14 | description = "The GCP project identifier where the cluster will be created." 15 | } 16 | variable "region" { 17 | type = string 18 | description = "The compute region which will host the BIG-IP VMs" 19 | } 20 | 21 | variable "zone" { 22 | type = string 23 | default = "us-central1-a" 24 | description = "The compute zones which will host the BIG-IP VMs" 25 | } 26 | variable "image" { 27 | type = string 28 | # default = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-4-1-0-53-5-payg-best-plus-25mbps-231026120516" 29 | description = "The self-link URI for a BIG-IP image to use as a base for the VM cluster.This can be an official F5 image from GCP Marketplace, or a customised image." 30 | } 31 | 32 | variable "service_account" { 33 | description = "service account email to use with BIG-IP vms" 34 | type = string 35 | } 36 | 37 | variable "metadata" { 38 | description = "Provide custom metadata values for BIG-IP instance" 39 | type = map(string) 40 | default = {} 41 | } 42 | 43 | 44 | variable "f5_ssh_publickey" { 45 | description = "Path to the public key to be used for ssh access to the VM. Only used with non-Windows vms and can be left as-is even if using Windows vms. If specifying a path to a certification on a Windows machine to provision a linux vm use the / in the path versus backslash. e.g. c:/home/id_rsa.pub" 46 | default = "~/.ssh/id_rsa.pub" 47 | } -------------------------------------------------------------------------------- /examples/bigip_gcp_4nic_deploy/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | } 4 | 5 | provider "google" { 6 | project = var.project_id 7 | region = var.region 8 | zone = var.zone 9 | } 10 | 11 | # 12 | # Create a random id 13 | # 14 | resource "random_id" "id" { 15 | byte_length = 2 16 | } 17 | 18 | resource "google_compute_network" "mgmt_network" { 19 | name = format("%s-mgmt-network-%s", var.prefix, random_id.id.hex) 20 | auto_create_subnetworks = false 21 | } 22 | resource "google_compute_subnetwork" "mgmt_subnetwork" { 23 | name = format("%s-mgmt-subnetwork-%s", var.prefix, random_id.id.hex) 24 | ip_cidr_range = "10.1.0.0/16" 25 | region = "us-central1" 26 | network = google_compute_network.mgmt_network.id 27 | } 28 | 29 | resource "google_compute_firewall" "default" { 30 | name = format("%s-mgmt-firewall-%s", var.prefix, random_id.id.hex) 31 | network = google_compute_network.mgmt_network.id 32 | allow { 33 | protocol = "tcp" 34 | ports = ["22", "80", "443", "8443"] 35 | } 36 | allow { 37 | protocol = "icmp" 38 | } 39 | source_ranges = ["0.0.0.0/0"] 40 | } 41 | 42 | resource "google_compute_network" "external_network" { 43 | name = format("%s-external-network-%s", var.prefix, random_id.id.hex) 44 | auto_create_subnetworks = false 45 | } 46 | 47 | resource "google_compute_subnetwork" "external_subnetwork" { 48 | name = format("%s-external-subnetwork-%s", var.prefix, random_id.id.hex) 49 | ip_cidr_range = "10.2.0.0/16" 50 | region = "us-central1" 51 | network = google_compute_network.external_network.id 52 | } 53 | 54 | resource "google_compute_firewall" "external" { 55 | name = format("%s-external-firewall-%s", var.prefix, random_id.id.hex) 56 | network = google_compute_network.external_network.id 57 | allow { 58 | protocol = "tcp" 59 | ports = ["22", "80", "443", "8443"] 60 | } 61 | allow { 62 | protocol = "icmp" 63 | } 64 | source_ranges = ["0.0.0.0/0"] 65 | } 66 | resource "google_compute_network" "internal_network" { 67 | name = format("%s-internal-network-%s", var.prefix, random_id.id.hex) 68 | auto_create_subnetworks = false 69 | } 70 | resource "google_compute_subnetwork" "internal_subnetwork" { 71 | name = format("%s-internal-subnetwork-%s", var.prefix, random_id.id.hex) 72 | ip_cidr_range = "10.3.0.0/16" 73 | region = "us-central1" 74 | network = google_compute_network.internal_network.id 75 | } 76 | resource "google_compute_firewall" "internal" { 77 | name = format("%s-internal-firewall-%s", var.prefix, random_id.id.hex) 78 | network = google_compute_network.internal_network.id 79 | allow { 80 | protocol = "tcp" 81 | ports = ["22", "80", "443", "8443"] 82 | } 83 | allow { 84 | protocol = "icmp" 85 | } 86 | source_ranges = ["0.0.0.0/0"] 87 | } 88 | resource "google_compute_network" "external_network2" { 89 | name = format("%s-external-network2-%s", var.prefix, random_id.id.hex) 90 | auto_create_subnetworks = false 91 | } 92 | 93 | resource "google_compute_subnetwork" "external_subnetwork2" { 94 | name = format("%s-external-subnetwork2-%s", var.prefix, random_id.id.hex) 95 | ip_cidr_range = "10.4.0.0/16" 96 | region = "us-central1" 97 | network = google_compute_network.external_network2.id 98 | } 99 | resource "google_compute_firewall" "external2" { 100 | name = format("%s-external2-firewall-%s", var.prefix, random_id.id.hex) 101 | network = google_compute_network.external_network2.id 102 | allow { 103 | protocol = "tcp" 104 | ports = ["22", "80", "443", "8443"] 105 | } 106 | allow { 107 | protocol = "icmp" 108 | } 109 | source_ranges = ["0.0.0.0/0"] 110 | } 111 | module "bigip" { 112 | count = var.instance_count 113 | source = "../.." 114 | prefix = format("%s-4nic", var.prefix) 115 | project_id = var.project_id 116 | zone = var.zone 117 | image = var.image 118 | service_account = var.service_account 119 | mgmt_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.mgmt_subnetwork.id, "public_ip" = true, "private_ip_primary" = "" }] 120 | external_subnet_ids = ([{ "subnet_id" = google_compute_subnetwork.external_subnetwork.id, "public_ip" = true, "private_ip_primary" = "", "private_ip_secondary" = "" }, { "subnet_id" = google_compute_subnetwork.external_subnetwork2.id, "public_ip" = true, "private_ip_primary" = "", "private_ip_secondary" = "" }]) 121 | internal_subnet_ids = [{ "subnet_id" = google_compute_subnetwork.internal_subnetwork.id, "public_ip" = false, "private_ip_primary" = "" }] 122 | } 123 | 124 | -------------------------------------------------------------------------------- /examples/bigip_gcp_4nic_deploy/output.tf: -------------------------------------------------------------------------------- 1 | output "bigip_password" { 2 | value = module.bigip.*.bigip_password 3 | } 4 | output "mgmtPublicIP" { 5 | value = module.bigip.*.mgmtPublicIP 6 | } 7 | output "bigip_username" { 8 | value = module.bigip.*.f5_username 9 | } 10 | output "mgmtPort" { 11 | value = module.bigip.*.mgmtPort 12 | } 13 | output "public_addresses" { 14 | value = module.bigip.*.public_addresses 15 | } 16 | output "private_addresses" { 17 | value = module.bigip.*.private_addresses 18 | } 19 | output "service_account" { 20 | value = module.bigip.*.service_account 21 | } 22 | -------------------------------------------------------------------------------- /examples/bigip_gcp_4nic_deploy/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-central1" 2 | prefix = "tf-gcp-bigip" -------------------------------------------------------------------------------- /examples/bigip_gcp_4nic_deploy/variables.tf: -------------------------------------------------------------------------------- 1 | variable "instance_count" { 2 | description = "Number of Bigip instances to create( From terraform 0.13, module supports count feature to spin mutliple instances )" 3 | type = number 4 | default = 1 5 | } 6 | variable "prefix" { 7 | description = "Prefix for resources created by this module" 8 | type = string 9 | default = "tf-gcp-bigip" 10 | } 11 | variable "project_id" { 12 | type = string 13 | description = "The GCP project identifier where the cluster will be created." 14 | } 15 | variable "region" { 16 | type = string 17 | description = "The compute region which will host the BIG-IP VMs" 18 | } 19 | variable "zone" { 20 | type = string 21 | default = "us-central1-a" 22 | description = "The compute zones which will host the BIG-IP VMs" 23 | } 24 | variable "image" { 25 | type = string 26 | default = "projects/f5-7626-networks-public/global/images/f5-bigip-16-1-2-2-0-0-28-payg-best-plus-25mbps-220505080809" 27 | description = "The self-link URI for a BIG-IP image to use as a base for the VM cluster.This can be an official F5 image from GCP Marketplace, or a customised image." 28 | } 29 | 30 | variable "service_account" { 31 | description = "service account email to use with BIG-IP vms" 32 | type = string 33 | } 34 | 35 | -------------------------------------------------------------------------------- /examples/terraform-webserver/outputs.tf: -------------------------------------------------------------------------------- 1 | output "webserver_ip" { 2 | value = google_compute_instance.vm.network_interface.0.access_config.0.nat_ip 3 | } 4 | -------------------------------------------------------------------------------- /examples/terraform-webserver/provider.tf: -------------------------------------------------------------------------------- 1 | # Specify the GCP Provider 2 | provider "google" { 3 | project = var.project_id 4 | region = var.region 5 | } 6 | -------------------------------------------------------------------------------- /examples/terraform-webserver/template/install_nginx.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | echo "***** Installing Nginx *****" 4 | apt update 5 | apt install -y nginx 6 | ufw allow '${ufw_allow_nginx}' 7 | systemctl enable nginx 8 | systemctl restart nginx 9 | 10 | echo "***** Installation Complteted!! *****" 11 | 12 | echo "Welcome to Google Compute VM Instance deployed using Terraform!!!" > /var/www/html/index.html 13 | 14 | echo "***** Startup script completes!! *****" 15 | -------------------------------------------------------------------------------- /examples/terraform-webserver/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-central1" 2 | prefix = "tf-gcp-bigip" 3 | labels = { 4 | "environment" = "dev" 5 | "team" = "devops" 6 | "application" = "webserver" 7 | } 8 | -------------------------------------------------------------------------------- /examples/terraform-webserver/testflask/main.tf: -------------------------------------------------------------------------------- 1 | # Specify the GCP Provider 2 | provider "google" { 3 | project = var.project_id 4 | region = var.region 5 | } 6 | 7 | 8 | https://artifactory.f5net.com/artifactory/f5-bigiq-mgmt-generic/images/releases/20.2.0/0.2.11/upgrade-bundle/BIG-IP-Next-CentralManager-20.2.0-0.2.11-Update.tgz 9 | 10 | # [START storage_flask_google_cloud_quickstart_parent_tag] 11 | # [START compute_flask_quickstart_vpc] 12 | resource "google_compute_network" "vpc_network" { 13 | name = "my-custom-mode-network" 14 | auto_create_subnetworks = false 15 | mtu = 1460 16 | } 17 | 18 | resource "google_compute_subnetwork" "default" { 19 | name = "my-custom-subnet" 20 | ip_cidr_range = "10.0.1.0/24" 21 | region = var.region 22 | network = google_compute_network.vpc_network.id 23 | } 24 | 25 | resource "google_compute_instance" "default" { 26 | name = "ravi-flask-vm" 27 | machine_type = "f1-micro" 28 | zone = var.zone 29 | tags = ["ssh"] 30 | 31 | boot_disk { 32 | initialize_params { 33 | image = "debian-cloud/debian-11" 34 | } 35 | } 36 | 37 | # Install Flask 38 | metadata_startup_script = "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask" 39 | 40 | network_interface { 41 | subnetwork = google_compute_subnetwork.default.id 42 | 43 | access_config { 44 | # Include this section to give the VM an external IP address 45 | } 46 | } 47 | } 48 | # [END compute_flask_quickstart_vm] 49 | 50 | # [START vpc_flask_quickstart_ssh_fw] 51 | resource "google_compute_firewall" "ssh" { 52 | name = "allow-ssh" 53 | allow { 54 | ports = ["22"] 55 | protocol = "tcp" 56 | } 57 | direction = "INGRESS" 58 | network = google_compute_network.vpc_network.id 59 | priority = 1000 60 | source_ranges = ["0.0.0.0/0"] 61 | target_tags = ["ssh"] 62 | } 63 | # [END vpc_flask_quickstart_ssh_fw] 64 | 65 | 66 | # [START vpc_flask_quickstart_5000_fw] 67 | resource "google_compute_firewall" "flask" { 68 | name = "flask-app-firewall" 69 | network = google_compute_network.vpc_network.id 70 | 71 | allow { 72 | protocol = "tcp" 73 | ports = ["5000"] 74 | } 75 | source_ranges = ["0.0.0.0/0"] 76 | } 77 | 78 | # # [END vpc_flask_quickstart_5000_fw] 79 | 80 | # # Create new multi-region storage bucket in the US 81 | # # with versioning enabled 82 | 83 | # # [START storage_kms_encryption_tfstate] 84 | # resource "google_kms_key_ring" "terraform_state" { 85 | # name = "${random_id.bucket_prefix.hex}-bucket-tfstate" 86 | # location = "us" 87 | # } 88 | 89 | # resource "google_kms_crypto_key" "terraform_state_bucket" { 90 | # name = "test-terraform-state-bucket" 91 | # key_ring = google_kms_key_ring.terraform_state.id 92 | # rotation_period = "86400s" 93 | 94 | # lifecycle { 95 | # prevent_destroy = false 96 | # } 97 | # } 98 | 99 | # # Enable the Cloud Storage service account to encrypt/decrypt Cloud KMS keys 100 | # data "google_project" "project" { 101 | # } 102 | 103 | # resource "google_project_iam_member" "default" { 104 | # project = data.google_project.project.project_id 105 | # role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" 106 | # member = "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com" 107 | # } 108 | # # [END storage_kms_encryption_tfstate] 109 | 110 | # # [START storage_bucket_tf_with_versioning] 111 | # resource "random_id" "bucket_prefix" { 112 | # byte_length = 8 113 | # } 114 | 115 | # resource "google_storage_bucket" "default" { 116 | # name = "${random_id.bucket_prefix.hex}-bucket-tfstate" 117 | # force_destroy = false 118 | # location = "US" 119 | # storage_class = "STANDARD" 120 | # versioning { 121 | # enabled = true 122 | # } 123 | # encryption { 124 | # default_kms_key_name = google_kms_crypto_key.terraform_state_bucket.id 125 | # } 126 | # depends_on = [ 127 | # google_project_iam_member.default 128 | # ] 129 | # } 130 | # # [END storage_bucket_tf_with_versioning] 131 | # # [END storage_flask_google_cloud_quickstart_parent_tag] -------------------------------------------------------------------------------- /examples/terraform-webserver/testflask/terraform.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-central1" 2 | prefix = "tf-gcp-bigip" 3 | labels = { 4 | "environment" = "dev" 5 | "team" = "devops" 6 | "application" = "webserver" 7 | } 8 | -------------------------------------------------------------------------------- /examples/terraform-webserver/testflask/variables.tf: -------------------------------------------------------------------------------- 1 | variable "project_id" { 2 | description = "Google Cloud Platform (GCP) Project ID." 3 | type = string 4 | } 5 | 6 | variable "region" { 7 | description = "GCP region name." 8 | type = string 9 | } 10 | 11 | variable "prefix" { 12 | description = "Prefix for resources created by this module" 13 | type = string 14 | default = "tf-gcp-bigip" 15 | } 16 | 17 | variable "zone" { 18 | type = string 19 | default = "us-central1-a" 20 | description = "The compute zones which will host the BIG-IP VMs" 21 | } 22 | 23 | variable "name" { 24 | description = "Web server name." 25 | type = string 26 | default = "my-nginx-webserver" 27 | } 28 | 29 | variable "machine_type" { 30 | description = "GCP VM instance machine type." 31 | type = string 32 | default = "f1-micro" 33 | } 34 | 35 | variable "labels" { 36 | description = "List of labels to attach to the VM instance." 37 | type = map(any) 38 | } 39 | -------------------------------------------------------------------------------- /examples/terraform-webserver/variables.tf: -------------------------------------------------------------------------------- 1 | variable "project_id" { 2 | description = "Google Cloud Platform (GCP) Project ID." 3 | type = string 4 | } 5 | 6 | variable "region" { 7 | description = "GCP region name." 8 | type = string 9 | } 10 | 11 | variable "prefix" { 12 | description = "Prefix for resources created by this module" 13 | type = string 14 | default = "tf-gcp-bigip" 15 | } 16 | 17 | variable "zone" { 18 | type = string 19 | default = "us-central1-a" 20 | description = "The compute zones which will host the BIG-IP VMs" 21 | } 22 | 23 | variable "name" { 24 | description = "Web server name." 25 | type = string 26 | default = "my-nginx-webserver" 27 | } 28 | 29 | variable "machine_type" { 30 | description = "GCP VM instance machine type." 31 | type = string 32 | default = "f1-micro" 33 | } 34 | 35 | variable "labels" { 36 | description = "List of labels to attach to the VM instance." 37 | type = map(any) 38 | } 39 | -------------------------------------------------------------------------------- /examples/terraform-webserver/vm.tf: -------------------------------------------------------------------------------- 1 | 2 | terraform { 3 | required_version = ">= 0.13" 4 | } 5 | 6 | # Create a random id 7 | # 8 | resource "random_id" "id" { 9 | byte_length = 2 10 | } 11 | 12 | # Create random password for BIG-IP 13 | # 14 | resource "random_string" "password" { 15 | length = 16 16 | min_upper = 1 17 | min_lower = 1 18 | min_numeric = 1 19 | special = false 20 | } 21 | 22 | resource "google_compute_network" "mgmtvpc" { 23 | name = format("%s-mgmtvpc-%s", var.prefix, random_id.id.hex) 24 | auto_create_subnetworks = false 25 | } 26 | 27 | resource "google_compute_network" "extvpc" { 28 | name = format("%s-extvpc-%s", var.prefix, random_id.id.hex) 29 | auto_create_subnetworks = false 30 | } 31 | 32 | # resource "google_compute_network" "intvpc" { 33 | # name = format("%s-intvpc-%s", var.prefix, random_id.id.hex) 34 | # auto_create_subnetworks = false 35 | # } 36 | 37 | resource "google_compute_subnetwork" "mgmt_subnetwork" { 38 | name = format("%s-mgmt-%s", var.prefix, random_id.id.hex) 39 | ip_cidr_range = "10.0.1.0/24" 40 | region = var.region 41 | network = google_compute_network.mgmtvpc.id 42 | } 43 | 44 | resource "google_compute_firewall" "mgmt_firewall" { 45 | name = format("%s-mgmt-firewall-%s", var.prefix, random_id.id.hex) 46 | network = google_compute_network.mgmtvpc.id 47 | allow { 48 | protocol = "tcp" 49 | ports = ["22", "80", "443", "8443"] 50 | } 51 | allow { 52 | protocol = "icmp" 53 | } 54 | source_ranges = ["0.0.0.0/0"] 55 | } 56 | 57 | resource "google_compute_subnetwork" "external_subnetwork" { 58 | name = format("%s-ext-%s", var.prefix, random_id.id.hex) 59 | ip_cidr_range = "10.0.2.0/24" 60 | region = var.region 61 | network = google_compute_network.extvpc.id 62 | } 63 | 64 | resource "google_compute_firewall" "ext_firewall" { 65 | name = format("%s-ext-firewall-%s", var.prefix, random_id.id.hex) 66 | network = google_compute_network.extvpc.id 67 | allow { 68 | protocol = "tcp" 69 | ports = ["22", "80", "443", "8443"] 70 | } 71 | allow { 72 | protocol = "icmp" 73 | } 74 | source_ranges = ["0.0.0.0/0"] 75 | } 76 | 77 | # resource "google_compute_subnetwork" "internal_subnetwork" { 78 | # name = format("%s-int-%s", var.prefix, random_id.id.hex) 79 | # ip_cidr_range = "10.0.3.0/24" 80 | # region = var.region 81 | # network = google_compute_network.intvpc.id 82 | # } 83 | 84 | data "google_compute_image" "ubuntu" { 85 | family = "ubuntu-2204-lts" 86 | project = "ubuntu-os-cloud" 87 | } 88 | 89 | 90 | # Creates a GCP VM Instance. Metadata Startup script install the Nginx webserver. 91 | resource "google_compute_instance" "vm" { 92 | name = var.name 93 | machine_type = var.machine_type 94 | zone = var.zone 95 | tags = ["http-server"] 96 | labels = var.labels 97 | 98 | boot_disk { 99 | initialize_params { 100 | image = data.google_compute_image.ubuntu.self_link 101 | } 102 | } 103 | network_interface { 104 | subnetwork = google_compute_subnetwork.mgmt_subnetwork.id 105 | access_config { 106 | // Ephemeral IP 107 | } 108 | } 109 | network_interface { 110 | subnetwork = google_compute_subnetwork.external_subnetwork.id 111 | } 112 | metadata = { 113 | sshKeys = file(var.vm_ssh_publickey) 114 | enable-oslogin = "TRUE" 115 | } 116 | metadata_startup_script = templatefile("template/install_nginx.tpl", { ufw_allow_nginx = "Nginx HTTP" }) 117 | } 118 | 119 | # Creates a GCP VM Instance. Metadata Startup script install the Nginx webserver. 120 | resource "google_compute_instance" "vm02" { 121 | name = format("%s-vm02", var.name) 122 | machine_type = var.machine_type 123 | zone = var.zone 124 | tags = ["http-server"] 125 | labels = var.labels 126 | 127 | boot_disk { 128 | initialize_params { 129 | image = data.google_compute_image.ubuntu.self_link 130 | } 131 | } 132 | network_interface { 133 | subnetwork = google_compute_subnetwork.external_subnetwork.id 134 | } 135 | metadata_startup_script = templatefile("template/install_nginx.tpl", { ufw_allow_nginx = "Nginx HTTP" }) 136 | } 137 | 138 | variable "vm_ssh_publickey" { 139 | description = "Path to the public key to be used for ssh access to the VM. Only used with non-Windows vms and can be left as-is even if using Windows vms. If specifying a path to a certification on a Windows machine to provision a linux vm use the / in the path versus backslash. e.g. c:/home/id_rsa.pub" 140 | default = "~/.ssh/id_rsa.pub" 141 | } -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | google = { 4 | source = "hashicorp/google" 5 | version = ">= 4.31.0" 6 | } 7 | } 8 | } 9 | # 10 | # Create a random id 11 | # 12 | resource "random_id" "module_id" { 13 | byte_length = 2 14 | } 15 | 16 | locals { 17 | # Emes - none of this commented section should be needed 18 | # bigip_map = { 19 | # "mgmt_subnet_ids" = var.mgmt_subnet_ids 20 | # "external_subnet_ids" = var.external_subnet_ids 21 | # "internal_subnet_ids" = var.internal_subnet_ids 22 | # } 23 | # mgmt_public_subnet_id = [ 24 | # for subnet in local.bigip_map["mgmt_subnet_ids"] : 25 | # subnet["subnet_id"] 26 | # if subnet["public_ip"] == true 27 | # ] 28 | # mgmt_private_subnet_id = [ 29 | # for subnet in local.bigip_map["mgmt_subnet_ids"] : 30 | # subnet["subnet_id"] 31 | # if subnet["public_ip"] == false 32 | # ] 33 | # mgmt_public_private_ip_primary = [ 34 | # for private in local.bigip_map["mgmt_subnet_ids"] : 35 | # private["private_ip_primary"] 36 | # if private["public_ip"] == true 37 | # ] 38 | # mgmt_private_ip_primary = [ 39 | # for private in local.bigip_map["mgmt_subnet_ids"] : 40 | # private["private_ip_primary"] 41 | # if private["public_ip"] == false 42 | # ] 43 | # external_public_subnet_id = [ 44 | # for subnet in local.bigip_map["external_subnet_ids"] : 45 | # subnet["subnet_id"] 46 | # if subnet["public_ip"] == true 47 | # ] 48 | # external_private_subnet_id = [ 49 | # for subnet in local.bigip_map["external_subnet_ids"] : 50 | # subnet["subnet_id"] 51 | # if subnet["public_ip"] == false 52 | # ] 53 | # internal_public_subnet_id = [ 54 | # for subnet in local.bigip_map["internal_subnet_ids"] : 55 | # subnet["subnet_id"] 56 | # if subnet["public_ip"] == true 57 | # ] 58 | # internal_private_subnet_id = [ 59 | # for subnet in local.bigip_map["internal_subnet_ids"] : 60 | # subnet["subnet_id"] 61 | # if subnet["public_ip"] == false 62 | # ] 63 | # internal_private_ip_primary = [ 64 | # for private in local.bigip_map["internal_subnet_ids"] : 65 | # private["private_ip_primary"] 66 | # if private["public_ip"] == false 67 | # ] 68 | # external_private_ip_primary = [ 69 | # for private in local.bigip_map["external_subnet_ids"] : 70 | # private["private_ip_primary"] 71 | # if private["public_ip"] == false 72 | # ] 73 | # external_private_ip_secondary = [ 74 | # for private in local.bigip_map["external_subnet_ids"] : 75 | # private["private_ip_secondary"] 76 | # if private["public_ip"] == false 77 | # ] 78 | # external_public_private_ip_primary = [ 79 | # for private in local.bigip_map["external_subnet_ids"] : 80 | # private["private_ip_primary"] 81 | # if private["public_ip"] == true 82 | # ] 83 | # external_public_private_ip_secondary = [ 84 | # for private in local.bigip_map["external_subnet_ids"] : 85 | # private["private_ip_secondary"] 86 | # if private["public_ip"] == true 87 | # ] 88 | # total_nics = length(concat(local.mgmt_public_subnet_id, local.mgmt_private_subnet_id, local.external_public_subnet_id, local.external_private_subnet_id, local.internal_public_subnet_id, local.internal_private_subnet_id)) 89 | external_nic_count = length([for subnet in var.external_subnet_ids : subnet if subnet.subnet_id != null && subnet.subnet_id != ""]) == 0 ? 0 : 1 90 | internal_nic_count = length([for subnet in var.internal_subnet_ids : subnet if subnet.subnet_id != null && subnet.subnet_id != ""]) == 0 ? 0 : 1 91 | multiple_nic_count = local.external_nic_count + local.internal_nic_count 92 | instance_prefix = format("%s-%s", var.prefix, random_id.module_id.hex) 93 | } 94 | 95 | resource "random_string" "password" { 96 | length = 16 97 | min_upper = 1 98 | min_lower = 1 99 | min_numeric = 1 100 | special = false 101 | } 102 | 103 | resource "random_string" "sa_role" { 104 | length = 16 105 | min_lower = 1 106 | numeric = false 107 | upper = false 108 | special = false 109 | } 110 | 111 | data "google_secret_manager_secret_version" "secret" { 112 | count = var.gcp_secret_manager_authentication ? 1 : 0 113 | secret = var.gcp_secret_name 114 | version = var.gcp_secret_version 115 | } 116 | 117 | resource "google_project_iam_member" "gcp_role_member_assignment" { 118 | count = var.gcp_secret_manager_authentication ? 1 : 0 119 | project = var.project_id 120 | role = format("projects/${var.project_id}/roles/%s", random_string.sa_role.result) 121 | member = "serviceAccount:${var.service_account}" 122 | } 123 | 124 | resource "google_project_iam_custom_role" "gcp_custom_roles" { 125 | count = var.gcp_secret_manager_authentication ? 1 : 0 126 | role_id = random_string.sa_role.result 127 | title = random_string.sa_role.result 128 | description = "IAM for authentication" 129 | permissions = ["secretmanager.versions.access"] 130 | } 131 | 132 | 133 | resource "google_compute_address" "mgmt_public_ip" { 134 | count = length([for address in compact([for subnet in var.mgmt_subnet_ids : subnet.public_ip]) : address if address]) 135 | name = format("%s-mgmt-publicip-%s", var.prefix, random_id.module_id.hex) 136 | } 137 | resource "google_compute_address" "external_public_ip" { 138 | count = length([for address in compact([for subnet in var.external_subnet_ids : subnet.public_ip]) : address if address]) 139 | name = format("%s-ext-publicip-%s-%s", var.prefix, count.index, random_id.module_id.hex) 140 | } 141 | 142 | resource "google_compute_instance" "f5vm01" { 143 | name = var.vm_name == "" ? format("%s", local.instance_prefix) : var.vm_name 144 | zone = var.zone 145 | # Scheduling options 146 | min_cpu_platform = var.min_cpu_platform 147 | machine_type = var.machine_type 148 | scheduling { 149 | automatic_restart = var.automatic_restart 150 | preemptible = var.preemptible 151 | } 152 | boot_disk { 153 | auto_delete = true 154 | initialize_params { 155 | type = var.disk_type 156 | size = var.disk_size_gb 157 | image = var.image 158 | } 159 | } 160 | service_account { 161 | email = var.service_account 162 | scopes = ["cloud-platform"] 163 | } 164 | can_ip_forward = true 165 | 166 | #Assign external Nic 167 | dynamic "network_interface" { 168 | for_each = [for subnet in var.external_subnet_ids : subnet if subnet.subnet_id != null && subnet.subnet_id != ""] 169 | content { 170 | subnetwork = network_interface.value.subnet_id 171 | network_ip = network_interface.value.private_ip_primary 172 | dynamic "access_config" { 173 | for_each = element(coalescelist(compact([network_interface.value.public_ip]), [false]), 0) ? [1] : [] 174 | content { 175 | nat_ip = google_compute_address.external_public_ip[tonumber(network_interface.key)].address 176 | } 177 | } 178 | dynamic "alias_ip_range" { 179 | for_each = compact([network_interface.value.private_ip_secondary]) 180 | content { 181 | ip_cidr_range = alias_ip_range.value 182 | } 183 | } 184 | } 185 | } 186 | 187 | 188 | #Assign to Management Nic 189 | dynamic "network_interface" { 190 | for_each = [for subnet in var.mgmt_subnet_ids : subnet if subnet.subnet_id != null && subnet.subnet_id != ""] 191 | content { 192 | subnetwork = network_interface.value.subnet_id 193 | network_ip = network_interface.value.private_ip_primary 194 | dynamic "access_config" { 195 | for_each = element(coalescelist(compact([network_interface.value.public_ip]), [false]), 0) ? [1] : [] 196 | content { 197 | nat_ip = google_compute_address.mgmt_public_ip[tonumber(network_interface.key)].address 198 | } 199 | } 200 | } 201 | } 202 | 203 | # Internal NIC 204 | dynamic "network_interface" { 205 | for_each = [for subnet in var.internal_subnet_ids : subnet if subnet.subnet_id != null && subnet.subnet_id != ""] 206 | content { 207 | subnetwork = network_interface.value.subnet_id 208 | network_ip = network_interface.value.private_ip_primary 209 | dynamic "access_config" { 210 | for_each = element(coalescelist(compact([network_interface.value.public_ip]), [false]), 0) ? [1] : [] 211 | content { 212 | nat_ip = google_compute_address.internal_public_ip[tonumber(network_interface.key)].address 213 | } 214 | } 215 | } 216 | } 217 | 218 | metadata_startup_script = replace(coalesce(var.custom_user_data, templatefile("${path.module}/startup-script-working.tpl", 219 | { 220 | onboard_log = var.onboard_log 221 | libs_dir = var.libs_dir 222 | bigip_username = var.f5_username 223 | gcp_secret_manager_authentication = var.gcp_secret_manager_authentication 224 | bigip_password = (var.f5_password == "") ? (var.gcp_secret_manager_authentication ? var.gcp_secret_name : random_string.password.result) : var.f5_password 225 | ssh_keypair = file(var.f5_ssh_publickey) 226 | INIT_URL = var.INIT_URL, 227 | DO_URL = var.DO_URL, 228 | DO_VER = format("v%s", split("-", split("/", var.DO_URL)[length(split("/", var.DO_URL)) - 1])[3]) 229 | AS3_URL = var.AS3_URL, 230 | AS3_VER = format("v%s", split("-", split("/", var.AS3_URL)[length(split("/", var.AS3_URL)) - 1])[2]) 231 | TS_VER = format("v%s", split("-", split("/", var.TS_URL)[length(split("/", var.TS_URL)) - 1])[2]) 232 | TS_URL = var.TS_URL, 233 | CFE_VER = format("v%s", split("-", split("/", var.CFE_URL)[length(split("/", var.CFE_URL)) - 1])[3]) 234 | CFE_URL = var.CFE_URL, 235 | FAST_URL = var.FAST_URL 236 | FAST_VER = format("v%s", split("-", split("/", var.FAST_URL)[length(split("/", var.FAST_URL)) - 1])[3]) 237 | NIC_COUNT = local.multiple_nic_count > 0 ? true : false 238 | })), "/\r/", "") 239 | 240 | metadata = merge(var.metadata, coalesce(var.f5_ssh_publickey, "unspecified") != "unspecified" ? { 241 | sshKeys = file(var.f5_ssh_publickey) 242 | } : {} 243 | ) 244 | labels = var.labels 245 | 246 | tags = var.network_tags 247 | 248 | } 249 | 250 | resource "time_sleep" "wait_for_google_compute_instance_f5vm" { 251 | depends_on = [google_compute_instance.f5vm01] 252 | create_duration = var.sleep_time 253 | } 254 | -------------------------------------------------------------------------------- /output.tf: -------------------------------------------------------------------------------- 1 | output "mgmtPublicIP" { 2 | value = join("", [for ac in google_compute_instance.f5vm01.network_interface[local.multiple_nic_count > 0 ? 1 : 0].access_config : ac.nat_ip if ac != null]) 3 | } 4 | output "mgmtPort" { 5 | description = "Mgmt Port" 6 | value = length(google_compute_instance.f5vm01.network_interface) > 1 ? "443" : "8443" 7 | } 8 | output "f5_username" { 9 | value = (var.custom_user_data == null) ? var.f5_username : "Username as provided in custom runtime-init" 10 | } 11 | output "bigip_password" { 12 | value = (var.custom_user_data == null) ? ((var.f5_password == "") ? (var.gcp_secret_manager_authentication ? data.google_secret_manager_secret_version.secret[0].secret_data : random_string.password.result) : var.f5_password) : "Password as provided in custom runtime-init" 13 | } 14 | output "public_addresses" { 15 | value = google_compute_instance.f5vm01.network_interface[*].access_config[*].nat_ip 16 | } 17 | output "private_addresses" { 18 | value = google_compute_instance.f5vm01.network_interface[*].network_ip 19 | } 20 | 21 | output "service_account" { 22 | value = var.service_account 23 | } 24 | 25 | output "self_link" { 26 | value = google_compute_instance.f5vm01.self_link 27 | description = "Fully-qualifed self-link of the BIG-IP VM." 28 | } 29 | 30 | output "name" { 31 | value = google_compute_instance.f5vm01.name 32 | description = "The final instance name for BIG-IP VM." 33 | } 34 | 35 | output "zone" { 36 | value = google_compute_instance.f5vm01.zone 37 | description = "The compute zone for the instance." 38 | } 39 | 40 | output "bigip_instance_ids" { 41 | value = concat(google_compute_instance.f5vm01.*.id)[0] 42 | } 43 | -------------------------------------------------------------------------------- /startup-script-backup.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Setup console and startup-script logging 3 | LOG_FILE=/var/log/cloud/startup-script.log 4 | mkdir -p /var/log/cloud 5 | [[ -f $LOG_FILE ]] || /usr/bin/touch $LOG_FILE 6 | npipe=/tmp/$$.tmp 7 | /usr/bin/trap "rm -f $npipe" EXIT 8 | /usr/bin/mknod $npipe p 9 | /usr/bin/tee <$npipe -a $LOG_FILE /dev/ttyS0 & 10 | exec 1>&- 11 | exec 1>$npipe 12 | exec 2>&1 13 | 14 | # Run Immediately Before MCPD starts 15 | /usr/bin/setdb provision.extramb 1024 16 | /usr/bin/setdb restjavad.useextramb true 17 | 18 | # skip startup script if already complete 19 | if [[ -f /config/startup_finished ]]; then 20 | echo "Onboarding complete, skip startup script" 21 | exit 22 | fi 23 | 24 | mkdir -p /config/cloud /var/config/rest/downloads /var/lib/cloud/icontrollx_installs 25 | 26 | # Create runtime configuration on first boot 27 | if [[ ! -f /config/nicswap_finished ]]; then 28 | cat << 'EOF' > /config/cloud/runtime-init-conf.yaml 29 | --- 30 | controls: 31 | extensionInstallDelayInMs: 60000 32 | runtime_parameters: 33 | - name: USER_NAME 34 | type: static 35 | value: ${bigip_username} 36 | - name: SSH_KEYS 37 | type: static 38 | value: "${ssh_keypair}" 39 | - name: HOST_NAME 40 | type: metadata 41 | metadataProvider: 42 | environment: gcp 43 | type: compute 44 | field: name 45 | EOF 46 | 47 | if ${gcp_secret_manager_authentication}; then 48 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 49 | - name: ADMIN_PASS 50 | type: secret 51 | secretProvider: 52 | environment: gcp 53 | type: SecretsManager 54 | version: latest 55 | secretId: ${bigip_password} 56 | pre_onboard_enabled: [] 57 | EOF 58 | else 59 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 60 | - name: ADMIN_PASS 61 | type: static 62 | value: ${bigip_password} 63 | pre_onboard_enabled: [] 64 | EOF 65 | fi 66 | 67 | cat /config/cloud/runtime-init-conf.yaml > /config/cloud/runtime-init-conf-backup.yaml 68 | 69 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 70 | extension_packages: 71 | install_operations: 72 | - extensionType: do 73 | extensionVersion: ${DO_VER} 74 | extensionUrl: ${DO_URL} 75 | - extensionType: as3 76 | extensionVersion: ${AS3_VER} 77 | extensionUrl: ${AS3_URL} 78 | - extensionType: ts 79 | extensionVersion: ${TS_VER} 80 | extensionUrl: ${TS_URL} 81 | - extensionType: cf 82 | extensionVersion: ${CFE_VER} 83 | extensionUrl: ${CFE_URL} 84 | - extensionType: fast 85 | extensionVersion: ${FAST_VER} 86 | extensionUrl: ${FAST_URL} 87 | extension_services: 88 | service_operations: 89 | - extensionType: do 90 | type: inline 91 | value: 92 | schemaVersion: 1.0.0 93 | class: Device 94 | async: true 95 | Common: 96 | class: Tenant 97 | hostname: '{{{HOST_NAME}}}.com' 98 | myNtp: 99 | class: NTP 100 | servers: 101 | - 169.254.169.254 102 | timezone: UTC 103 | myDns: 104 | class: DNS 105 | nameServers: 106 | - 169.254.169.254 107 | myProvisioning: 108 | class: Provision 109 | ltm: nominal 110 | admin: 111 | class: User 112 | partitionAccess: 113 | all-partitions: 114 | role: admin 115 | password: '{{{ADMIN_PASS}}}' 116 | shell: bash 117 | keys: 118 | - '{{{SSH_KEYS}}}' 119 | userType: regular 120 | '{{{USER_NAME}}}': 121 | class: User 122 | partitionAccess: 123 | all-partitions: 124 | role: admin 125 | password: '{{{ADMIN_PASS}}}' 126 | shell: bash 127 | keys: 128 | - '{{{SSH_KEYS}}}' 129 | userType: regular 130 | post_onboard_enabled: [] 131 | EOF 132 | 133 | cat << 'EOF' >> /config/cloud/runtime-init-conf-backup.yaml 134 | extension_services: 135 | service_operations: 136 | - extensionType: do 137 | type: inline 138 | value: 139 | schemaVersion: 1.0.0 140 | class: Device 141 | async: true 142 | Common: 143 | class: Tenant 144 | hostname: '{{{HOST_NAME}}}.com' 145 | myNtp: 146 | class: NTP 147 | servers: 148 | - 169.254.169.254 149 | timezone: UTC 150 | myDns: 151 | class: DNS 152 | nameServers: 153 | - 169.254.169.254 154 | myProvisioning: 155 | class: Provision 156 | ltm: nominal 157 | admin: 158 | class: User 159 | partitionAccess: 160 | all-partitions: 161 | role: admin 162 | password: '{{{ADMIN_PASS}}}' 163 | shell: bash 164 | keys: 165 | - '{{{SSH_KEYS}}}' 166 | userType: regular 167 | '{{{USER_NAME}}}': 168 | class: User 169 | partitionAccess: 170 | all-partitions: 171 | role: admin 172 | password: '{{{ADMIN_PASS}}}' 173 | shell: bash 174 | keys: 175 | - '{{{SSH_KEYS}}}' 176 | userType: regular 177 | post_onboard_enabled: [] 178 | EOF 179 | fi 180 | 181 | # Create nic_swap script when multi nic on first boot 182 | COMPUTE_BASE_URL="http://metadata.google.internal/computeMetadata/v1" 183 | 184 | if [[ ${NIC_COUNT} && ! -f /config/nicswap_finished ]]; then 185 | cat << 'EOF' > /config/cloud/nic_swap.sh 186 | #!/bin/bash 187 | source /usr/lib/bigstart/bigip-ready-functions 188 | wait_bigip_ready 189 | echo "before nic swapping" 190 | tmsh list sys db provision.1nicautoconfig 191 | tmsh list sys db provision.managementeth 192 | echo "after nic swapping" 193 | bigstart stop tmm 194 | echo "ip addr" 195 | ip addr 196 | /usr/bin/cat /etc/ts/common/image.cfg 197 | echo "Done changing interface" 198 | if [[ -f /config/nicswap_finished ]]; then 199 | echo "Skip first run steps, already ran." 200 | else 201 | tmsh modify sys db provision.managementeth value eth1 202 | sed -i "s/iface0=eth0/iface0=eth1/g" /etc/ts/common/image.cfg 203 | /usr/bin/touch /config/nicswap_finished 204 | reboot 205 | fi 206 | EOF 207 | fi 208 | 209 | # Create run_runtime_init.sh script on first boot 210 | if [ ! -f /config/nicswap_finished ]; then 211 | cat << 'EOF' > /config/cloud/run_runtime_init.sh 212 | #!/bin/bash 213 | source /usr/lib/bigstart/bigip-ready-functions 214 | wait_bigip_ready 215 | if ${NIC_COUNT} ; then 216 | echo "Running Multi NIC Changes for Management" 217 | echo "---Mgmt interface setting---" 218 | tmsh list sys db provision.managementeth 219 | tmsh list sys db provision.1nicautoconfig 220 | echo "Set TMM networks" 221 | ip r s 222 | # Wait until a little more until dhcp/chmand is finished re-configuring MGMT IP w/ "chmand[4267]: 012a0003:3: Mgmt Operation:0 Dest:0.0.0.0" 223 | MGMTADDRESS=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/ip) 224 | NONMGMTADDRESS=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip) 225 | MGMTMASK=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/subnetmask) 226 | MGMTGATEWAY=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/gateway) 227 | MGMTMTU=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/mtu) 228 | MGMTNETWORK=$(/bin/ipcalc -n $MGMTADDRESS $MGMTMASK | cut -d= -f2) 229 | # tmsh modify sys global-settings mgmt-dhcp disabled 230 | # tmsh delete sys management-route all 231 | # tmsh delete sys management-ip all 232 | # wait_bigip_ready 233 | # # Wait until a little more until dhcp/chmand is finished re-configuring MGMT IP w/ "chmand[4267]: 012a0003:3: Mgmt Operation:0 Dest:0.0.0.0" 234 | # sleep 15 235 | # MGMT_GW=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | grep -oE \'[^ ]+$\' | tr -d \';\') 236 | # SELF_IP_MGMT=$(egrep fixed-address /var/lib/dhclient/dhclient.leases | tail -1 | grep -oE \'[^ ]+$\' | tr -d \';\') 237 | # MGMT_BITMASK=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | cut -d \\' -f 2 | cut -d \' \' -f 1 | cut -d \'.\' -f 1) 238 | # MGMT_NETWORK=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | cut -d \\' -f 2 | cut -d \' \' -f 1 | cut -d \'.\' -f 2-4).0 239 | echo $MGMTADDRESS 240 | echo $MGMTMASK 241 | echo $MGMTGATEWAY 242 | echo $MGMTMTU 243 | echo $MGMTNETWORK 244 | echo $NONMGMTADDRESS 245 | tmsh modify sys global-settings gui-setup disabled 246 | tmsh modify sys global-settings mgmt-dhcp disabled 247 | tmsh delete sys management-route all 248 | tmsh delete sys management-ip all 249 | echo "ip r s default via $NONMGMTADDRESS" 250 | /usr/bin/ip route delete default via $NONMGMTADDRESS 251 | tmsh delete sys management-ip all 252 | tmsh create sys management-ip $MGMTADDRESS/32 253 | echo "tmsh list sys management-ip - " 254 | tmsh list sys management-ip 255 | tmsh create sys management-route mgmt_gw network $MGMTGATEWAY/32 type interface mtu $MGMTMTU 256 | tmsh create sys management-route mgmt_net network $MGMTNETWORK/$MGMTMASK gateway $MGMTGATEWAY mtu $MGMTMTU 257 | tmsh create sys management-route defaultManagementRoute network default gateway $MGMTGATEWAY mtu $MGMTMTU 258 | tmsh modify sys global-settings remote-host add { metadata.google.internal { hostname metadata.google.internal addr 169.254.169.254 } } 259 | tmsh modify sys management-dhcp sys-mgmt-dhcp-config request-options delete { ntp-servers } 260 | echo "Setting DNS resolver to Cloud DNS" 261 | tmsh modify sys dns name-servers add { 169.254.169.254 } 262 | tmsh save /sys config 263 | echo "ip r s" 264 | ip r s 265 | echo "dig cdn.f5.com" 266 | dig cdn.f5.com 267 | echo "dig google.com done" 268 | fi 269 | for i in {1..30}; do 270 | curl -fv --retry 1 --connect-timeout 5 -L ${INIT_URL} -o "/var/config/rest/downloads/f5-bigip-runtime-init.gz.run" && break || sleep 10 271 | done 272 | bash /var/config/rest/downloads/f5-bigip-runtime-init.gz.run -- '--cloud gcp' 2>&1 273 | /usr/bin/cat /config/cloud/runtime-init-conf.yaml 274 | /usr/local/bin/f5-bigip-runtime-init --config-file /config/cloud/runtime-init-conf.yaml 2>&1 275 | sleep 5 276 | /usr/bin/cat /config/cloud/runtime-init-conf-backup.yaml 277 | /usr/local/bin/f5-bigip-runtime-init --config-file /config/cloud/runtime-init-conf-backup.yaml 2>&1 278 | sleep 5 279 | /usr/local/bin/f5-bigip-runtime-init --config-file /config/cloud/runtime-init-conf-backup.yaml 2>&1 280 | /usr/bin/touch /config/startup_finished 281 | EOF 282 | fi 283 | 284 | ls -ltr /config 285 | sleep 15 286 | # Run scripts based on number of nics 287 | if [[ ${NIC_COUNT} && -f /config/nicswap_finished ]];then 288 | echo "Running run_runtime_init.sh" 289 | chmod +x /config/cloud/run_runtime_init.sh 290 | nohup /config/cloud/run_runtime_init.sh & 291 | else 292 | echo "Running nic_swap.sh" 293 | chmod +x /config/cloud/nic_swap.sh 294 | nohup /config/cloud/nic_swap.sh & 295 | fi 296 | if ! ${NIC_COUNT} ;then 297 | echo "Running run_runtime_init.sh" 298 | chmod +x /config/cloud/run_runtime_init.sh 299 | nohup /config/cloud/run_runtime_init.sh & 300 | fi -------------------------------------------------------------------------------- /startup-script-working.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Setup console and startup-script logging 3 | LOG_FILE=/var/log/cloud/startup-script.log 4 | mkdir -p /var/log/cloud 5 | [[ -f $LOG_FILE ]] || /usr/bin/touch $LOG_FILE 6 | npipe=/tmp/$$.tmp 7 | /usr/bin/trap "rm -f $npipe" EXIT 8 | /usr/bin/mknod $npipe p 9 | /usr/bin/tee <$npipe -a $LOG_FILE /dev/ttyS0 & 10 | exec 1>&- 11 | exec 1>$npipe 12 | exec 2>&1 13 | 14 | # Run Immediately Before MCPD starts 15 | /usr/bin/setdb provision.extramb 1024 16 | /usr/bin/setdb restjavad.useextramb true 17 | 18 | # skip startup script if already complete 19 | if [[ -f /config/startup_finished ]]; then 20 | echo "Onboarding complete, skip startup script" 21 | exit 22 | fi 23 | 24 | mkdir -p /config/cloud /var/config/rest/downloads /var/lib/cloud/icontrollx_installs 25 | 26 | # Create runtime configuration on first boot 27 | if [[ ! -f /config/nicswap_finished ]]; then 28 | cat << 'EOF' > /config/cloud/runtime-init-conf.yaml 29 | --- 30 | controls: 31 | extensionInstallDelayInMs: 60000 32 | runtime_parameters: 33 | - name: USER_NAME 34 | type: static 35 | value: ${bigip_username} 36 | - name: SSH_KEYS 37 | type: static 38 | value: "${ssh_keypair}" 39 | - name: HOST_NAME 40 | type: metadata 41 | metadataProvider: 42 | environment: gcp 43 | type: compute 44 | field: name 45 | EOF 46 | 47 | if ${gcp_secret_manager_authentication}; then 48 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 49 | - name: ADMIN_PASS 50 | type: secret 51 | secretProvider: 52 | environment: gcp 53 | type: SecretsManager 54 | version: latest 55 | secretId: ${bigip_password} 56 | pre_onboard_enabled: [] 57 | EOF 58 | else 59 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 60 | - name: ADMIN_PASS 61 | type: static 62 | value: ${bigip_password} 63 | pre_onboard_enabled: [] 64 | EOF 65 | fi 66 | 67 | cat /config/cloud/runtime-init-conf.yaml > /config/cloud/runtime-init-conf-backup.yaml 68 | 69 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 70 | extension_packages: 71 | install_operations: 72 | - extensionType: do 73 | extensionVersion: ${DO_VER} 74 | extensionUrl: ${DO_URL} 75 | - extensionType: as3 76 | extensionVersion: ${AS3_VER} 77 | extensionUrl: ${AS3_URL} 78 | - extensionType: ts 79 | extensionVersion: ${TS_VER} 80 | extensionUrl: ${TS_URL} 81 | - extensionType: cf 82 | extensionVersion: ${CFE_VER} 83 | extensionUrl: ${CFE_URL} 84 | - extensionType: fast 85 | extensionVersion: ${FAST_VER} 86 | extensionUrl: ${FAST_URL} 87 | extension_services: 88 | service_operations: 89 | - extensionType: do 90 | type: inline 91 | value: 92 | schemaVersion: 1.0.0 93 | class: Device 94 | async: true 95 | Common: 96 | class: Tenant 97 | hostname: '{{{HOST_NAME}}}.com' 98 | myNtp: 99 | class: NTP 100 | servers: 101 | - 169.254.169.254 102 | timezone: UTC 103 | myDns: 104 | class: DNS 105 | nameServers: 106 | - 169.254.169.254 107 | myProvisioning: 108 | class: Provision 109 | ltm: nominal 110 | admin: 111 | class: User 112 | partitionAccess: 113 | all-partitions: 114 | role: admin 115 | password: '{{{ADMIN_PASS}}}' 116 | shell: bash 117 | keys: 118 | - '{{{SSH_KEYS}}}' 119 | userType: regular 120 | '{{{USER_NAME}}}': 121 | class: User 122 | partitionAccess: 123 | all-partitions: 124 | role: admin 125 | password: '{{{ADMIN_PASS}}}' 126 | shell: bash 127 | keys: 128 | - '{{{SSH_KEYS}}}' 129 | userType: regular 130 | post_onboard_enabled: [] 131 | EOF 132 | 133 | cat << 'EOF' >> /config/cloud/runtime-init-conf-backup.yaml 134 | extension_services: 135 | service_operations: 136 | - extensionType: do 137 | type: inline 138 | value: 139 | schemaVersion: 1.0.0 140 | class: Device 141 | async: true 142 | Common: 143 | class: Tenant 144 | hostname: '{{{HOST_NAME}}}.com' 145 | myNtp: 146 | class: NTP 147 | servers: 148 | - 169.254.169.254 149 | timezone: UTC 150 | myDns: 151 | class: DNS 152 | nameServers: 153 | - 169.254.169.254 154 | myProvisioning: 155 | class: Provision 156 | ltm: nominal 157 | admin: 158 | class: User 159 | partitionAccess: 160 | all-partitions: 161 | role: admin 162 | password: '{{{ADMIN_PASS}}}' 163 | shell: bash 164 | keys: 165 | - '{{{SSH_KEYS}}}' 166 | userType: regular 167 | '{{{USER_NAME}}}': 168 | class: User 169 | partitionAccess: 170 | all-partitions: 171 | role: admin 172 | password: '{{{ADMIN_PASS}}}' 173 | shell: bash 174 | keys: 175 | - '{{{SSH_KEYS}}}' 176 | userType: regular 177 | post_onboard_enabled: [] 178 | EOF 179 | fi 180 | 181 | # Create nic_swap script when multi nic on first boot 182 | COMPUTE_BASE_URL="http://metadata.google.internal/computeMetadata/v1" 183 | 184 | if [[ ${NIC_COUNT} && ! -f /config/nicswap_finished ]]; then 185 | cat << 'EOF' >> /config/cloud/nic_swap.sh 186 | #!/bin/bash 187 | source /usr/lib/bigstart/bigip-ready-functions 188 | wait_bigip_ready 189 | echo "before nic swapping" 190 | tmsh list sys db provision.1nicautoconfig 191 | tmsh list sys db provision.managementeth 192 | echo "after nic swapping" 193 | bigstart stop tmm 194 | tmsh modify sys db provision.managementeth value eth1 195 | tmsh modify sys db provision.1nicautoconfig value disable 196 | bigstart start tmm 197 | wait_bigip_ready 198 | echo "---Mgmt interface setting---" 199 | tmsh list sys db provision.managementeth 200 | tmsh list sys db provision.1nicautoconfig 201 | sed -i "s/iface0=eth0/iface0=eth1/g" /etc/ts/common/image.cfg 202 | echo "Done changing interface" 203 | echo "Set TMM networks" 204 | MGMTADDRESS=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/ip) 205 | MGMTMASK=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/subnetmask) 206 | MGMTGATEWAY=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/gateway) 207 | MGMTMTU=$(curl -s -f --retry 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/mtu) 208 | MGMTNETWORK=$(/bin/ipcalc -n $MGMTADDRESS $MGMTMASK | cut -d= -f2) 209 | echo $MGMTADDRESS 210 | echo $MGMTMASK 211 | echo $MGMTGATEWAY 212 | echo $MGMTMTU 213 | echo $MGMTNETWORK 214 | tmsh modify sys global-settings gui-setup disabled 215 | tmsh modify sys global-settings mgmt-dhcp disabled 216 | tmsh delete sys management-route all 217 | tmsh delete sys management-ip all 218 | tmsh create sys management-ip $${MGMTADDRESS}/32 219 | tmsh create sys management-route mgmt_gw network $${MGMTGATEWAY}/32 type interface mtu $${MGMTMTU} 220 | tmsh create sys management-route mgmt_net network $${MGMTNETWORK}/$${MGMTMASK} gateway $${MGMTGATEWAY} mtu $${MGMTMTU} 221 | tmsh create sys management-route default gateway $${MGMTGATEWAY} mtu $${MGMTMTU} 222 | tmsh modify sys global-settings remote-host add { metadata.google.internal { hostname metadata.google.internal addr 169.254.169.254 } } 223 | tmsh modify sys management-dhcp sys-mgmt-dhcp-config request-options delete { ntp-servers } 224 | echo "Setting DNS resolver to Cloud DNS" 225 | tmsh modify sys dns name-servers add { 169.254.169.254 } 226 | tmsh save /sys config 227 | /usr/bin/touch /config/nicswap_finished 228 | reboot 229 | EOF 230 | fi 231 | 232 | # Create run_runtime_init.sh script on first boot 233 | if [[ ! -f /config/nicswap_finished ]]; then 234 | cat << 'EOF' >> /config/cloud/run_runtime_init.sh 235 | #!/bin/bash 236 | source /usr/lib/bigstart/bigip-ready-functions 237 | wait_bigip_ready 238 | for i in {1..30}; do 239 | curl -fv --retry 1 --connect-timeout 5 -L ${INIT_URL} -o "/var/config/rest/downloads/f5-bigip-runtime-init.gz.run" && break || sleep 10 240 | done 241 | bash /var/config/rest/downloads/f5-bigip-runtime-init.gz.run -- '--cloud gcp' 2>&1 242 | /usr/local/bin/f5-bigip-runtime-init --config-file /config/cloud/runtime-init-conf.yaml 2>&1 243 | sleep 5 244 | /usr/local/bin/f5-bigip-runtime-init --config-file /config/cloud/runtime-init-conf-backup.yaml 2>&1 245 | sleep 5 246 | /usr/local/bin/f5-bigip-runtime-init --config-file /config/cloud/runtime-init-conf-backup.yaml 2>&1 247 | /usr/bin/touch /config/startup_finished 248 | EOF 249 | fi 250 | 251 | # Run scripts based on number of nics 252 | if ${NIC_COUNT}; then 253 | if [[ -f /config/nicswap_finished ]]; then 254 | echo "Running run_runtime_init.sh" 255 | chmod +x /config/cloud/run_runtime_init.sh 256 | nohup /config/cloud/run_runtime_init.sh & 257 | else 258 | chmod +x /config/cloud/nic_swap.sh 259 | nohup /config/cloud/nic_swap.sh & 260 | fi 261 | else 262 | echo "Running run_runtime_init.sh" 263 | chmod +x /config/cloud/run_runtime_init.sh 264 | nohup /config/cloud/run_runtime_init.sh & 265 | fi 266 | -------------------------------------------------------------------------------- /startup-script.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -f /config/startup_finished ]; then 3 | exit 4 | fi 5 | if [ -f /config/first_run_flag ]; then 6 | echo "Skip first run steps, already ran." 7 | else 8 | /usr/bin/mkdir -p /var/log/cloud /config/cloud /var/lib/cloud/icontrollx_installs /var/config/rest/downloads 9 | LOG_FILE=/var/log/cloud/startup-script-pre-nic-swap.log 10 | /usr/bin/touch $LOG_FILE 11 | npipe=/tmp/$$.tmp 12 | /usr/bin/trap "rm -f $npipe" EXIT 13 | /usr/bin/mknod $npipe p 14 | /usr/bin/tee <$npipe -a $LOG_FILE /dev/ttyS0 & 15 | exec 1>&- 16 | exec 1>$npipe 17 | exec 2>&1 18 | cat << 'EOF' > /config/cloud/runtime-init-conf.yaml 19 | --- 20 | controls: 21 | extensionInstallDelayInMs: 60000 22 | runtime_parameters: 23 | - name: USER_NAME 24 | type: static 25 | value: ${bigip_username} 26 | - name: SSH_KEYS 27 | type: static 28 | value: "${ssh_keypair}" 29 | - name: HOST_NAME 30 | type: metadata 31 | metadataProvider: 32 | environment: gcp 33 | type: compute 34 | field: name 35 | EOF 36 | if ${gcp_secret_manager_authentication}; then 37 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 38 | - name: ADMIN_PASS 39 | type: secret 40 | secretProvider: 41 | environment: gcp 42 | type: SecretsManager 43 | version: latest 44 | secretId: ${bigip_password} 45 | pre_onboard_enabled: [] 46 | EOF 47 | else 48 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 49 | - name: ADMIN_PASS 50 | type: static 51 | value: ${bigip_password} 52 | pre_onboard_enabled: [] 53 | EOF 54 | fi 55 | cat /config/cloud/runtime-init-conf.yaml > /config/cloud/runtime-init-conf-backup.yaml 56 | cat << 'EOF' >> /config/cloud/runtime-init-conf.yaml 57 | extension_packages: 58 | install_operations: 59 | - extensionType: do 60 | extensionVersion: ${DO_VER} 61 | extensionUrl: ${DO_URL} 62 | - extensionType: as3 63 | extensionVersion: ${AS3_VER} 64 | extensionUrl: ${AS3_URL} 65 | - extensionType: ts 66 | extensionVersion: ${TS_VER} 67 | extensionUrl: ${TS_URL} 68 | - extensionType: cf 69 | extensionVersion: ${CFE_VER} 70 | extensionUrl: ${CFE_URL} 71 | - extensionType: fast 72 | extensionVersion: ${FAST_VER} 73 | extensionUrl: ${FAST_URL} 74 | extension_services: 75 | service_operations: 76 | - extensionType: do 77 | type: inline 78 | value: 79 | schemaVersion: 1.0.0 80 | class: Device 81 | async: true 82 | Common: 83 | class: Tenant 84 | hostname: '{{{HOST_NAME}}}.com' 85 | myNtp: 86 | class: NTP 87 | servers: 88 | - 169.254.169.254 89 | timezone: UTC 90 | myDns: 91 | class: DNS 92 | nameServers: 93 | - 169.254.169.254 94 | myProvisioning: 95 | class: Provision 96 | ltm: nominal 97 | admin: 98 | class: User 99 | partitionAccess: 100 | all-partitions: 101 | role: admin 102 | password: '{{{ADMIN_PASS}}}' 103 | shell: bash 104 | keys: 105 | - '{{{SSH_KEYS}}}' 106 | userType: regular 107 | '{{{USER_NAME}}}': 108 | class: User 109 | partitionAccess: 110 | all-partitions: 111 | role: admin 112 | password: '{{{ADMIN_PASS}}}' 113 | shell: bash 114 | keys: 115 | - '{{{SSH_KEYS}}}' 116 | userType: regular 117 | post_onboard_enabled: [] 118 | EOF 119 | cat << 'EOF' >> /config/cloud/runtime-init-conf-backup.yaml 120 | extension_services: 121 | service_operations: 122 | - extensionType: do 123 | type: inline 124 | value: 125 | schemaVersion: 1.0.0 126 | class: Device 127 | async: true 128 | Common: 129 | class: Tenant 130 | hostname: '{{{HOST_NAME}}}.com' 131 | myNtp: 132 | class: NTP 133 | servers: 134 | - 169.254.169.254 135 | timezone: UTC 136 | myDns: 137 | class: DNS 138 | nameServers: 139 | - 169.254.169.254 140 | myProvisioning: 141 | class: Provision 142 | ltm: nominal 143 | admin: 144 | class: User 145 | partitionAccess: 146 | all-partitions: 147 | role: admin 148 | password: '{{{ADMIN_PASS}}}' 149 | shell: bash 150 | keys: 151 | - '{{{SSH_KEYS}}}' 152 | userType: regular 153 | '{{{USER_NAME}}}': 154 | class: User 155 | partitionAccess: 156 | all-partitions: 157 | role: admin 158 | password: '{{{ADMIN_PASS}}}' 159 | shell: bash 160 | keys: 161 | - '{{{SSH_KEYS}}}' 162 | userType: regular 163 | post_onboard_enabled: [] 164 | EOF 165 | /usr/bin/cat << 'EOF' > /config/nic-swap.sh 166 | #!/bin/bash 167 | /usr/bin/touch /config/nic_swap_flag 168 | /usr/bin/setdb provision.managementeth eth1 169 | /usr/bin/setdb provision.extramb 1000 || true 170 | /usr/bin/setdb provision.restjavad.extramb 1384 || /usr/bin/setdb restjavad.useextramb true || true 171 | /usr/bin/setdb iapplxrpm.timeout 300 || true 172 | /usr/bin/setdb icrd.timeout 180 || true 173 | /usr/bin/setdb restjavad.timeout 180 || true 174 | /usr/bin/setdb restnoded.timeout 180 || true 175 | reboot 176 | EOF 177 | /usr/bin/cat << 'EOF' > /config/startup-script.sh 178 | #!/bin/bash 179 | LOG_FILE=/var/log/cloud/startup-script-post-swap-nic.log 180 | touch $LOG_FILE 181 | npipe=/tmp/$$.tmp 182 | /usr/bin/trap "rm -f $npipe" EXIT 183 | /usr/bin/mknod $npipe p 184 | /usr/bin/tee <$npipe -a $LOG_FILE /dev/ttyS0 & 185 | exec 1>&- 186 | exec 1>$npipe 187 | exec 2>&1 188 | if ${NIC_COUNT} ; then 189 | # Need to remove existing and recreate a MGMT default route as not provided by DHCP on 2nd NIC Route name must be same as in DO config. 190 | source /usr/lib/bigstart/bigip-ready-functions 191 | wait_bigip_ready 192 | tmsh modify sys global-settings mgmt-dhcp disabled 193 | tmsh delete sys management-route all 194 | tmsh delete sys management-ip all 195 | wait_bigip_ready 196 | # Wait until a little more until dhcp/chmand is finished re-configuring MGMT IP w/ "chmand[4267]: 012a0003:3: Mgmt Operation:0 Dest:0.0.0.0" 197 | sleep 15 198 | MGMT_GW=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | grep -oE '[^ ]+$' | tr -d ';') 199 | SELF_IP_MGMT=$(egrep fixed-address /var/lib/dhclient/dhclient.leases | tail -1 | grep -oE '[^ ]+$' | tr -d ';') 200 | MGMT_BITMASK=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | cut -d ',' -f 2 | cut -d ' ' -f 1 | cut -d '.' -f 1) 201 | MGMT_NETWORK=$(egrep static-routes /var/lib/dhclient/dhclient.leases | tail -1 | cut -d ',' -f 2 | cut -d ' ' -f 1 | cut -d '.' -f 2-4).0 202 | echo "MGMT_GW - " 203 | echo $MGMT_GW 204 | echo "SELF_IP_MGMT - " 205 | echo $SELF_IP_MGMT 206 | echo "MGMT_BITMASK - " 207 | echo $MGMT_BITMASK 208 | echo "MGMT_NETWORK - " 209 | echo $MGMT_NETWORK 210 | tmsh create sys management-ip $SELF_IP_MGMT/32 211 | echo "tmsh list sys management-ip - " 212 | tmsh list sys management-ip 213 | tmsh create sys management-route mgmt_gw network $MGMT_GW/32 type interface 214 | tmsh create sys management-route mgmt_net network $MGMT_NETWORK/$MGMT_BITMASK gateway $MGMT_GW 215 | tmsh create sys management-route defaultManagementRoute network default gateway $MGMT_GW mtu 1460 216 | echo "tmsh list sys management-route - " 217 | tmsh list sys management-route 218 | tmsh modify sys global-settings remote-host add { metadata.google.internal { hostname metadata.google.internal addr 169.254.169.254 } } 219 | tmsh save /sys config 220 | fi 221 | for i in {1..30}; do 222 | curl -fv --retry 1 --connect-timeout 5 -L ${INIT_URL} -o "/var/config/rest/downloads/f5-bigip-runtime-init.gz.run" && break || sleep 10 223 | done 224 | # install and run f5-bigip-runtime-init 225 | bash /var/config/rest/downloads/f5-bigip-runtime-init.gz.run -- '--cloud gcp' 226 | /usr/bin/cat /config/cloud/runtime-init-conf.yaml 227 | /usr/local/bin/f5-bigip-runtime-init --config-file /config/cloud/runtime-init-conf.yaml 228 | sleep 5 229 | /usr/local/bin/f5-bigip-runtime-init --config-file /config/cloud/runtime-init-conf-backup.yaml 230 | /usr/bin/touch /config/startup_finished 231 | EOF 232 | /usr/bin/chmod +x /config/nic-swap.sh 233 | /usr/bin/chmod +x /config/startup-script.sh 234 | MULTI_NIC="${NIC_COUNT}" 235 | /usr/bin/touch /config/first_run_flag 236 | fi 237 | if ${NIC_COUNT} ; then 238 | nohup /config/nic-swap.sh & 239 | else 240 | /usr/bin/touch /config/nic_swap_flag 241 | fi 242 | if [ -f /config/nic_swap_flag ]; then 243 | nohup /config/startup-script.sh & 244 | fi -------------------------------------------------------------------------------- /test/gcp_bigip_1nic_unit_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "strings" 7 | "testing" 8 | "time" 9 | 10 | http_helper "github.com/gruntwork-io/terratest/modules/http-helper" 11 | "github.com/gruntwork-io/terratest/modules/terraform" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func TestTerraformGCP1NicExample(t *testing.T) { 16 | 17 | t.Parallel() 18 | 19 | terraformOptions := &terraform.Options{ 20 | 21 | TerraformDir: "../examples/bigip_gcp_1nic_deploy", 22 | 23 | Vars: map[string]interface{}{ 24 | "region": "us-central1", 25 | }, 26 | } 27 | 28 | defer terraform.Destroy(t, terraformOptions) 29 | 30 | terraform.InitAndApply(t, terraformOptions) 31 | 32 | mgmtPublicIP := strings.Trim(terraform.Output(t, terraformOptions, "mgmtPublicIP"), "[]") 33 | bigipPassword := strings.Trim(terraform.Output(t, terraformOptions, "bigip_password"), "[]") 34 | bigipUsername := strings.Trim(terraform.Output(t, terraformOptions, "bigip_username"), "[]") 35 | mgmtPort := strings.Trim(terraform.Output(t, terraformOptions, "mgmtPort"), "[]") 36 | 37 | assert.NotEqual(t, "", mgmtPublicIP) 38 | assert.NotEqual(t, "", bigipPassword) 39 | assert.Equal(t, "bigipuser", bigipUsername) 40 | assert.Equal(t, "8443", mgmtPort) 41 | 42 | as3Url := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/appsvcs/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 43 | doUrl := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/declarative-onboarding/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 44 | // as3Url := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/appsvcs/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 45 | 46 | // Setup a TLS configuration to submit with the helper, a blank struct is acceptable 47 | tlsConfig := tls.Config{ 48 | InsecureSkipVerify: true, 49 | } 50 | 51 | http_helper.HttpGetWithRetryWithCustomValidation( 52 | t, 53 | as3Url, 54 | &tlsConfig, 55 | 10, 56 | 10*time.Second, 57 | verifyAs3Resp, 58 | ) 59 | http_helper.HttpGetWithRetryWithCustomValidation( 60 | t, 61 | doUrl, 62 | &tlsConfig, 63 | 10, 64 | 10*time.Second, 65 | verifyDoResp, 66 | ) 67 | } 68 | 69 | func verifyAs3Resp(statusCode int, body string) bool { 70 | var respStr = `{"version":"3.34.0","release":"4","schemaCurrent":"3.34.0","schemaMinimum":"3.0.0"}` 71 | return statusCode == 200 && strings.Contains(body, respStr) 72 | } 73 | 74 | func verifyDoResp(statusCode int, body string) bool { 75 | var respStr = `"version":"1.27.0"` 76 | return statusCode == 200 && strings.Contains(body, respStr) 77 | } 78 | -------------------------------------------------------------------------------- /test/gcp_bigip_2nic_unit_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "strings" 7 | "testing" 8 | "time" 9 | 10 | http_helper "github.com/gruntwork-io/terratest/modules/http-helper" 11 | "github.com/gruntwork-io/terratest/modules/terraform" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func TestTerraformGCP2NicExample(t *testing.T) { 16 | 17 | t.Parallel() 18 | 19 | terraformOptions := &terraform.Options{ 20 | 21 | TerraformDir: "../examples/bigip_gcp_2nic_deploy", 22 | 23 | Vars: map[string]interface{}{ 24 | "region": "us-central1", 25 | }, 26 | } 27 | 28 | defer terraform.Destroy(t, terraformOptions) 29 | 30 | terraform.InitAndApply(t, terraformOptions) 31 | 32 | mgmtPublicIP := strings.Trim(terraform.Output(t, terraformOptions, "mgmtPublicIP"), "[]") 33 | bigipPassword := strings.Trim(terraform.Output(t, terraformOptions, "bigip_password"), "[]") 34 | bigipUsername := strings.Trim(terraform.Output(t, terraformOptions, "bigip_username"), "[]") 35 | mgmtPort := strings.Trim(terraform.Output(t, terraformOptions, "mgmtPort"), "[]") 36 | 37 | assert.NotEqual(t, "", mgmtPublicIP) 38 | assert.NotEqual(t, "", bigipPassword) 39 | assert.Equal(t, "bigipuser", bigipUsername) 40 | assert.Equal(t, "443", mgmtPort) 41 | 42 | as3Url := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/appsvcs/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 43 | doUrl := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/declarative-onboarding/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 44 | // as3Url := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/appsvcs/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 45 | 46 | // Setup a TLS configuration to submit with the helper, a blank struct is acceptable 47 | tlsConfig := tls.Config{ 48 | InsecureSkipVerify: true, 49 | } 50 | 51 | http_helper.HttpGetWithRetryWithCustomValidation( 52 | t, 53 | as3Url, 54 | &tlsConfig, 55 | 10, 56 | 10*time.Second, 57 | verifyAs3Resp, 58 | ) 59 | http_helper.HttpGetWithRetryWithCustomValidation( 60 | t, 61 | doUrl, 62 | &tlsConfig, 63 | 10, 64 | 10*time.Second, 65 | verifyDoResp, 66 | ) 67 | } 68 | 69 | func verifyAs3Resp(statusCode int, body string) bool { 70 | var respStr = `{"version":"3.34.0","release":"4","schemaCurrent":"3.34.0","schemaMinimum":"3.0.0"}` 71 | return statusCode == 200 && strings.Contains(body, respStr) 72 | } 73 | 74 | func verifyDoResp(statusCode int, body string) bool { 75 | var respStr = `"version":"1.27.0"` 76 | return statusCode == 200 && strings.Contains(body, respStr) 77 | } 78 | -------------------------------------------------------------------------------- /test/gcp_bigip_3nic_unit_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "strings" 7 | "testing" 8 | "time" 9 | 10 | http_helper "github.com/gruntwork-io/terratest/modules/http-helper" 11 | "github.com/gruntwork-io/terratest/modules/terraform" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func TestTerraformGCP3NicExample(t *testing.T) { 16 | 17 | t.Parallel() 18 | 19 | terraformOptions := &terraform.Options{ 20 | 21 | TerraformDir: "../examples/bigip_gcp_3nic_deploy", 22 | 23 | Vars: map[string]interface{}{ 24 | "region": "us-central1", 25 | }, 26 | } 27 | 28 | defer terraform.Destroy(t, terraformOptions) 29 | 30 | terraform.InitAndApply(t, terraformOptions) 31 | 32 | mgmtPublicIP := strings.Trim(terraform.Output(t, terraformOptions, "mgmtPublicIP"), "[]") 33 | bigipPassword := strings.Trim(terraform.Output(t, terraformOptions, "bigip_password"), "[]") 34 | bigipUsername := strings.Trim(terraform.Output(t, terraformOptions, "bigip_username"), "[]") 35 | mgmtPort := strings.Trim(terraform.Output(t, terraformOptions, "mgmtPort"), "[]") 36 | 37 | assert.NotEqual(t, "", mgmtPublicIP) 38 | assert.NotEqual(t, "", bigipPassword) 39 | assert.Equal(t, "bigipuser", bigipUsername) 40 | assert.Equal(t, "443", mgmtPort) 41 | 42 | as3Url := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/appsvcs/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 43 | doUrl := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/declarative-onboarding/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 44 | // as3Url := fmt.Sprintf("https://%s:%s@%s:%s/mgmt/shared/appsvcs/info", bigipUsername, bigipPassword, mgmtPublicIP, mgmtPort) 45 | 46 | // Setup a TLS configuration to submit with the helper, a blank struct is acceptable 47 | tlsConfig := tls.Config{ 48 | InsecureSkipVerify: true, 49 | } 50 | 51 | http_helper.HttpGetWithRetryWithCustomValidation( 52 | t, 53 | as3Url, 54 | &tlsConfig, 55 | 10, 56 | 10*time.Second, 57 | verifyAs3Resp, 58 | ) 59 | http_helper.HttpGetWithRetryWithCustomValidation( 60 | t, 61 | doUrl, 62 | &tlsConfig, 63 | 10, 64 | 10*time.Second, 65 | verifyDoResp, 66 | ) 67 | } 68 | func verifyAs3Resp(statusCode int, body string) bool { 69 | var respStr = `{"version":"3.34.0","release":"4","schemaCurrent":"3.34.0","schemaMinimum":"3.0.0"}` 70 | return statusCode == 200 && strings.Contains(body, respStr) 71 | } 72 | 73 | func verifyDoResp(statusCode int, body string) bool { 74 | var respStr = `"version":"1.27.0"` 75 | return statusCode == 200 && strings.Contains(body, respStr) 76 | } 77 | -------------------------------------------------------------------------------- /test/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/F5Networks/terraform-gcp-bigip-module 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.23.2 6 | 7 | require ( 8 | github.com/gruntwork-io/terratest v0.47.1 9 | github.com/stretchr/testify v1.9.0 10 | ) 11 | 12 | require ( 13 | cloud.google.com/go v0.110.0 // indirect 14 | cloud.google.com/go/compute v1.19.1 // indirect 15 | cloud.google.com/go/compute/metadata v0.2.3 // indirect 16 | cloud.google.com/go/iam v0.13.0 // indirect 17 | cloud.google.com/go/storage v1.28.1 // indirect 18 | github.com/agext/levenshtein v1.2.3 // indirect 19 | github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect 20 | github.com/aws/aws-sdk-go v1.44.122 // indirect 21 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect 22 | github.com/davecgh/go-spew v1.1.1 // indirect 23 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 24 | github.com/golang/protobuf v1.5.3 // indirect 25 | github.com/google/go-cmp v0.5.9 // indirect 26 | github.com/google/uuid v1.3.0 // indirect 27 | github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect 28 | github.com/googleapis/gax-go/v2 v2.7.1 // indirect 29 | github.com/hashicorp/errwrap v1.0.0 // indirect 30 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 31 | github.com/hashicorp/go-getter v1.7.6 // indirect 32 | github.com/hashicorp/go-multierror v1.1.0 // indirect 33 | github.com/hashicorp/go-safetemp v1.0.0 // indirect 34 | github.com/hashicorp/go-version v1.6.0 // indirect 35 | github.com/hashicorp/hcl/v2 v2.9.1 // indirect 36 | github.com/hashicorp/terraform-json v0.13.0 // indirect 37 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect 38 | github.com/jmespath/go-jmespath v0.4.0 // indirect 39 | github.com/klauspost/compress v1.15.11 // indirect 40 | github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect 41 | github.com/mitchellh/go-homedir v1.1.0 // indirect 42 | github.com/mitchellh/go-testing-interface v1.14.1 // indirect 43 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 44 | github.com/pmezard/go-difflib v1.0.0 // indirect 45 | github.com/tmccombs/hcl2json v0.3.3 // indirect 46 | github.com/ulikunitz/xz v0.5.10 // indirect 47 | github.com/zclconf/go-cty v1.9.1 // indirect 48 | go.opencensus.io v0.24.0 // indirect 49 | golang.org/x/crypto v0.37.0 // indirect 50 | golang.org/x/net v0.39.0 // indirect 51 | golang.org/x/oauth2 v0.8.0 // indirect 52 | golang.org/x/sys v0.32.0 // indirect 53 | golang.org/x/text v0.24.0 // indirect 54 | golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect 55 | google.golang.org/api v0.114.0 // indirect 56 | google.golang.org/appengine v1.6.7 // indirect 57 | google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect 58 | google.golang.org/grpc v1.56.3 // indirect 59 | google.golang.org/protobuf v1.33.0 // indirect 60 | gopkg.in/yaml.v3 v3.0.1 // indirect 61 | ) 62 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "prefix" { 2 | description = "Prefix for resources created by this module" 3 | } 4 | 5 | variable "vm_name" { 6 | description = "Name of F5 BIGIP VM to be used, default is empty string meaning module adds with prefix + random_id" 7 | default = "" 8 | } 9 | 10 | variable "project_id" { 11 | type = string 12 | description = "The GCP project identifier where the cluster will be created." 13 | } 14 | 15 | variable "zone" { 16 | type = string 17 | description = "The compute zones which will host the BIG-IP VMs" 18 | } 19 | 20 | variable "min_cpu_platform" { 21 | type = string 22 | default = "Intel Skylake" 23 | description = "Minimum CPU platform for the VM instance such as Intel Haswell or Intel Skylake" 24 | } 25 | 26 | variable "machine_type" { 27 | type = string 28 | default = "n1-standard-8" 29 | description = "The machine type to create,if you want to update this value (resize the VM) after initial creation, you must set allow_stopping_for_update to true" 30 | } 31 | 32 | variable "automatic_restart" { 33 | type = bool 34 | default = true 35 | description = "Specifies if the instance should be restarted if it was terminated by Compute Engine (not a user),defaults to true." 36 | } 37 | 38 | variable "preemptible" { 39 | type = string 40 | default = false 41 | description = "Specifies if the instance is preemptible. If this field is set to true, then automatic_restart must be set to false,defaults to false." 42 | } 43 | 44 | variable "image" { 45 | type = string 46 | default = "projects/f5-7626-networks-public/global/images/f5-bigip-17-1-1-4-0-0-9-payg-best-plus-200mbps-240902171748" 47 | description = "This can be one of: the image's self_link, projects/{project}/global/images/{image}, projects/{project}/global/images/family/{family}, global/images/{image}, global/images/family/{family}, family/{family}, {project}/{family}, {project}/{image}, {family}, or {image}." 48 | } 49 | 50 | variable "disk_type" { 51 | type = string 52 | default = "pd-ssd" 53 | description = "The GCE disk type. May be set to pd-standard, pd-balanced or pd-ssd." 54 | } 55 | 56 | variable "disk_size_gb" { 57 | type = number 58 | default = null 59 | description = " The size of the image in gigabytes. If not specified, it will inherit the size of its base image." 60 | } 61 | 62 | variable "mgmt_subnet_ids" { 63 | description = "List of maps of subnetids of the virtual network where the virtual machines will reside." 64 | type = list(object({ 65 | subnet_id = string 66 | public_ip = bool 67 | private_ip_primary = string 68 | })) 69 | default = [{ "subnet_id" = null, "public_ip" = null, "private_ip_primary" = null }] 70 | } 71 | 72 | variable "external_subnet_ids" { 73 | description = "List of maps of subnetids of the virtual network where the virtual machines will reside." 74 | type = list(object({ 75 | subnet_id = string 76 | public_ip = bool 77 | private_ip_primary = string 78 | private_ip_secondary = string 79 | })) 80 | default = [{ "subnet_id" = null, "public_ip" = null, "private_ip_primary" = null, "private_ip_secondary" = null }] 81 | } 82 | 83 | variable "internal_subnet_ids" { 84 | description = "List of maps of subnetids of the virtual network where the virtual machines will reside." 85 | type = list(object({ 86 | subnet_id = string 87 | public_ip = bool 88 | private_ip_primary = string 89 | })) 90 | default = [{ "subnet_id" = null, "public_ip" = null, "private_ip_primary" = null }] 91 | } 92 | 93 | 94 | variable "f5_username" { 95 | description = "The admin username of the F5 Bigip that will be deployed" 96 | default = "bigipuser" 97 | } 98 | 99 | variable "f5_password" { 100 | description = "The admin password of the F5 Bigip that will be deployed" 101 | default = "" 102 | } 103 | 104 | variable "onboard_log" { 105 | description = "Directory on the BIG-IP to store the cloud-init logs" 106 | default = "/var/log/startup-script.log" 107 | type = string 108 | } 109 | 110 | variable "libs_dir" { 111 | description = "Directory on the BIG-IP to download the A&O Toolchain into" 112 | default = "/config/cloud/gcp/node_modules" 113 | type = string 114 | } 115 | 116 | variable "gcp_secret_manager_authentication" { 117 | description = "Whether to use secret manager to pass authentication" 118 | type = bool 119 | default = false 120 | } 121 | 122 | variable "gcp_secret_name" { 123 | description = "The secret to get the secret version for" 124 | type = string 125 | default = "" 126 | } 127 | 128 | variable "gcp_secret_version" { 129 | description = "(Optional)The version of the secret to get. If it is not provided, the latest version is retrieved." 130 | type = string 131 | default = "latest" 132 | } 133 | 134 | ## Please check and update the latest DO URL from https://github.com/F5Networks/f5-declarative-onboarding/releases 135 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 136 | variable "DO_URL" { 137 | description = "URL to download the BIG-IP Declarative Onboarding module" 138 | type = string 139 | default = "https://github.com/F5Networks/f5-declarative-onboarding/releases/download/v1.46.0/f5-declarative-onboarding-1.46.0-7.noarch.rpm" 140 | } 141 | ## Please check and update the latest AS3 URL from https://github.com/F5Networks/f5-appsvcs-extension/releases/latest 142 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 143 | variable "AS3_URL" { 144 | description = "URL to download the BIG-IP Application Service Extension 3 (AS3) module" 145 | type = string 146 | default = "https://github.com/F5Networks/f5-appsvcs-extension/releases/download/v3.53.0/f5-appsvcs-3.53.0-7.noarch.rpm" 147 | } 148 | 149 | ## Please check and update the latest TS URL from https://github.com/F5Networks/f5-telemetry-streaming/releases/latest 150 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 151 | variable "TS_URL" { 152 | description = "URL to download the BIG-IP Telemetry Streaming module" 153 | type = string 154 | default = "https://github.com/F5Networks/f5-telemetry-streaming/releases/download/v1.37.0/f5-telemetry-1.37.0-1.noarch.rpm" 155 | } 156 | 157 | ## Please check and update the latest Failover Extension URL from https://github.com/F5Networks/f5-cloud-failover-extension/releases/latest 158 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 159 | variable "CFE_URL" { 160 | description = "URL to download the BIG-IP Cloud Failover Extension module" 161 | type = string 162 | default = "https://github.com/F5Networks/f5-cloud-failover-extension/releases/download/v2.1.3/f5-cloud-failover-2.1.3-3.noarch.rpm" 163 | } 164 | 165 | ## Please check and update the latest FAST URL from https://github.com/F5Networks/f5-appsvcs-templates/releases/latest 166 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 167 | variable "FAST_URL" { 168 | description = "URL to download the BIG-IP FAST module" 169 | type = string 170 | default = "https://github.com/F5Networks/f5-appsvcs-templates/releases/download/v1.25.0/f5-appsvcs-templates-1.25.0-1.noarch.rpm" 171 | } 172 | ## Please check and update the latest runtime init URL from https://github.com/F5Networks/f5-bigip-runtime-init/releases/latest 173 | # always point to a specific version in order to avoid inadvertent configuration inconsistency 174 | variable "INIT_URL" { 175 | description = "URL to download the BIG-IP runtime init" 176 | type = string 177 | default = "https://cdn.f5.com/product/cloudsolutions/f5-bigip-runtime-init/v2.0.3/dist/f5-bigip-runtime-init-2.0.3-1.gz.run" 178 | } 179 | 180 | variable "labels" { 181 | description = "An optional map of key:value labels to add to the instance" 182 | type = map(string) 183 | default = {} 184 | } 185 | 186 | variable "service_account" { 187 | description = "service account email to use with BIG-IP vms" 188 | type = string 189 | } 190 | 191 | variable "f5_ssh_publickey" { 192 | description = "Path to the public key to be used for ssh access to the VM. Only used with non-Windows vms and can be left as-is even if using Windows vms. If specifying a path to a certification on a Windows machine to provision a linux vm use the / in the path versus backslash. e.g. c:/home/id_rsa.pub" 193 | default = "~/.ssh/id_rsa.pub" 194 | } 195 | 196 | variable "custom_user_data" { 197 | description = "Provide a custom bash script or cloud-init script the BIG-IP will run on creation" 198 | type = string 199 | default = null 200 | } 201 | 202 | variable "metadata" { 203 | description = "Provide custom metadata values for BIG-IP instance" 204 | type = map(string) 205 | default = {} 206 | } 207 | 208 | variable "sleep_time" { 209 | type = string 210 | default = "1000s" 211 | description = "The number of seconds/minutes of delay to build into creation of BIG-IP VMs; default is 250. BIG-IP requires a few minutes to complete the onboarding process and this value can be used to delay the processing of dependent Terraform resources." 212 | } 213 | 214 | variable "network_tags" { 215 | type = list(string) 216 | default = [] 217 | description = "The network tags which will be added to the BIG-IP VMs" 218 | } 219 | --------------------------------------------------------------------------------