├── LICENSE ├── README.md ├── advanced_Concepts ├── dependency_graph.md ├── import.md ├── parallel_execution.md └── state_file.md ├── course_overview.md ├── deployment1 ├── client.tf ├── cloudinit.yaml ├── infra.png ├── mykey ├── mykey.pub ├── output.tf ├── server.tf └── vars.tf ├── deployment2 ├── README.md ├── cloudinit1.yaml ├── cloudinit2.yaml ├── deploy2.jpg ├── output.tf ├── stack.tf └── vars.tf ├── exercises ├── cloudinit.yaml ├── ex1.tf ├── ex10.tf ├── ex1a.tf ├── ex2.tf ├── ex3.png ├── ex3.tf ├── ex4.tf ├── mykey └── mykey.pub ├── lbaas ├── README.md ├── cloudinit1.yaml ├── cloudinit2.yaml ├── lbaas.jpg ├── output.tf ├── stack.tf └── vars.tf ├── provisioner ├── README.md ├── file_prov │ ├── prov_ex3.tf │ ├── test.txt │ └── vars.tf ├── local_exec │ ├── prov_ex1.tf │ └── vars.tf ├── null_resource │ ├── output.tf │ ├── stack.tf │ └── vars.tf └── remote_exec │ ├── prov_ex2.tf │ ├── test.sh │ └── vars.tf ├── terraform_commands.md ├── terraform_example_deployment.md ├── terraform_exercises_part1.md ├── terraform_exercises_part2.md ├── terraform_exercises_part3.md ├── terraform_exercises_part4.md ├── terraform_how_to_write.md ├── terraform_installation.md ├── terraform_introduction.md └── todo.txt /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 | # learn-terraform-with-openstack 2 | 3 | This is **Learn terraform with openstack provider** UDEMY COURSE tutorials. 4 | 5 | Click below to access the Terraform course in UDEMY (Promo Price - $9.99) 6 | 7 | [link to Terraform UDEMY Course](https://www.udemy.com/learn-terraform-with-openstack-practical-exercises/?couponCode=PROMO1) 8 | 9 | ## This Training tutorial is organized as below, 10 | 11 | ### Introduction: 12 | 13 | 1. [Course Overview](course_overview.md) 14 | 2. [Introduction](terraform_introduction.md) 15 | 3. [Installation](terraform_installation.md) 16 | 4. [Basic Commands](terraform_commands.md) 17 | 5. [How to write stack](terraform_how_to_write.md) 18 | 19 | ### Basic Exercies: 20 | 21 | 6. [Exercise1](terraform_exercises_part1.md) 22 | 7. [Exercise2](terraform_exercises_part2.md) 23 | 8. [Exercise3](terraform_exercises_part3.md) 24 | 9. [Exercise4](terraform_exercises_part4.md) 25 | 26 | ### Provisioner: 27 | 28 | 10. [Provisioner](provisioner/README.md) 29 | 30 | ### Some Concepts: 31 | 32 | 11. parallel execution 33 | 12. dependency Graph 34 | 13. state file 35 | 14. import 36 | 37 | 38 | ### Deployment1 - : Bigger Infra 39 | 40 | **Learning points: Bigger topology (Router, multiple networks, servers)** 41 | 42 | 15. [Example Deployment1](terraform_example_deployment.md) 43 | 44 | 45 | ### Deployment2 - : conditional execution 46 | 47 | **Learning Points: Terraform - Count, Element(), Conditional Execution** 48 | 49 | 16. [Example Deployment2](deployment2/README.md) 50 | 51 | 52 | ### Deployment3 - : Load balancer stack 53 | 54 | **Learning Points: LBAASv2 orchestration.** 55 | 56 | 17. [Loadbalancer Deployment](lbaas/README.md) 57 | 58 | 59 | 60 | ## Author 61 | ========== 62 | 63 | Myself Suresh Kumar, Instructor of this Course. I have been working in the Networking,Telecommunication Software industry for past 15 Years. Engaged with Openstack, SDN, Cloud Projects for last 5 years. 64 | 65 | If You need any assistance, yon contact me on skype id: **SURESHKVL** or by mail: sureshkumarr.s@gmail.com 66 | -------------------------------------------------------------------------------- /advanced_Concepts/dependency_graph.md: -------------------------------------------------------------------------------- 1 | #Dependency Graph 2 | 3 | Todo -------------------------------------------------------------------------------- /advanced_Concepts/import.md: -------------------------------------------------------------------------------- 1 | #Import 2 | 3 | Todo -------------------------------------------------------------------------------- /advanced_Concepts/parallel_execution.md: -------------------------------------------------------------------------------- 1 | #Parallel Execution 2 | 3 | Todo -------------------------------------------------------------------------------- /advanced_Concepts/state_file.md: -------------------------------------------------------------------------------- 1 | #State File 2 | Todo -------------------------------------------------------------------------------- /course_overview.md: -------------------------------------------------------------------------------- 1 | Learn Terraform with Openstack Provider 2 | ======================================== 3 | 4 | This is a crash course to learn TERRAFORM with hands on exercises in Openstack Cloud. 5 | 6 | This course is primarily built for Beginners, who wants to learn Terraform with practical exercises and writes your simple Infrastructure in Openstack. 7 | 8 | In this course, we uses the Terraform and Openstack. 9 | 10 | This course covers only OPENSTACK provider. 11 | 12 | This course DOESNOT cover any other providers (AWS, GOOGLE CLOUD, VMWARE etc). 13 | 14 | 15 | Course Overview 16 | ==================== 17 | 18 | 1. Terraform Introduction 19 | 20 | 2. Terraform Installation 21 | 22 | 3. Terraform Commands 23 | 24 | 4. Terrfaform - How to write Configuration (infra as a code) 25 | 26 | 5. Terraform - Exercises (Openstack) 27 | 28 | step by step guide to write the the infra in openstack cloud using terrafrom configuration 29 | 30 | 6. Terraform - Example deployment 31 | 32 | -------------------------------------------------------------------------------- /deployment1/client.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_networking_network_v2" "client_net" { 2 | name = "client_net" 3 | admin_state_up = "true" 4 | } 5 | 6 | resource "openstack_networking_subnet_v2" "client_subnet" { 7 | name = "client_subnet" 8 | network_id = "${openstack_networking_network_v2.client_net.id}" 9 | cidr = "172.1.1.0/24" 10 | } 11 | 12 | resource "openstack_networking_router_interface_v2" "client_net_itf" { 13 | router_id = "${openstack_networking_router_v2.internet_router.id}" 14 | subnet_id = "${openstack_networking_subnet_v2.client_subnet.id}" 15 | } 16 | 17 | resource "openstack_compute_instance_v2" "client1" { 18 | name = "client1" 19 | image_id = "${var.clientimage}" 20 | flavor_id = "${var.clientflavor}" 21 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 22 | network { 23 | uuid = "${openstack_networking_network_v2.client_net.id}" 24 | } 25 | } 26 | 27 | resource "openstack_compute_instance_v2" "client2" { 28 | name = "client2" 29 | image_id = "${var.clientimage}" 30 | flavor_id = "${var.clientflavor}" 31 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 32 | network { 33 | uuid = "${openstack_networking_network_v2.client_net.id}" 34 | } 35 | } 36 | 37 | 38 | resource "openstack_networking_floatingip_v2" "fip_2" { 39 | pool = "public" 40 | } 41 | 42 | 43 | resource "openstack_compute_floatingip_associate_v2" "fip_2" { 44 | floating_ip = "${openstack_networking_floatingip_v2.fip_2.address}" 45 | instance_id = "${openstack_compute_instance_v2.client1.id}" 46 | } 47 | 48 | -------------------------------------------------------------------------------- /deployment1/cloudinit.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | package_update: true 3 | packages: 4 | - apache2 5 | runcmd: 6 | - sudo a2enmod ssl 7 | - sudo a2ensite default-ssl 8 | - sudo service apache2 restart 9 | - echo `hostname` | sudo tee /var/www/html/index.html 10 | output: 11 | final: '> /dev/ttyS0' 12 | -------------------------------------------------------------------------------- /deployment1/infra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/learn-terraform-with-openstack/aec4f95243126956a189438c314f29b235ecc20f/deployment1/infra.png -------------------------------------------------------------------------------- /deployment1/mykey: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEArNAEwm7jYt70Kakg6Q7TYne9v9++6ENRYyFoWV9lYKLmHgzk 3 | 3lVjTWsPBpSrvjkeNJX3Mj7lXegmVQKVNMOc9fk26mysk4Mi90Xcu+Ieas6MrrJL 4 | mkhq0eW8Oe09kHr6aHwOBkxHI/pzTBWGeaYVCD3joniRxS1DBnhS4O+RH8VTlWfW 5 | qrco4hA9ky36yWOD+p0o10JpAMp/kzQT8AK5MyG6PS1KDt+fCuVHbm1T9STqp6bD 6 | Y2G0E05q/LuENDLHShD72ncI+dGj5v+GnYQo1HN61/NdILyuGHV3CeRtehpnNFgF 7 | ftD5ixBRsgl5IdlLK2/gUTHmwMO3KXjdRjH6yQIDAQABAoIBAB8o7wLEDdohC3OL 8 | nHSJiNIDd0JmrLyijsVKG8+ppNT06ntWpdn1GY+3EyGDoygMkoa217jGoIL7PhYr 9 | /g1ijCXKBv3kFIYQqjhd73wtPIDTt4g0e+9YyXIJc5QaU/R+SDKY08qM7HLvUOTS 10 | KMo8iSRQTIBaLyaXj7NV9NO8PrW0ihCJ+ktvngrTBpAh3mGyxGXtaqPw0fFiagr9 11 | 84gyy0eQcehU+4GXiPzPumWOL8NbAtp/d7l4QG+7HdQwj+cjARxadD+8KyxvkbK3 12 | Lidw3Z9DYz90CYzsXiQFQ+KErOcNTikNE4vmZ90ILvTiF1VJbprDn2WtDx0uCxWW 13 | GuiaZgECgYEA0x73PSyhj3SYnitxOo/D3Zf+cDtDLeecxJ9bhwRvJ/xSJQFyozt2 14 | zhJT/nl0VZkPR+VzehqPIzzfZXtDjH+r9JvqNXBNbXP1x3BHLD53/eJlOWFDbtV3 15 | 1H0nwXi0NB6OwF4HPSvRxt2dzVpQVzkYe1YLAbXkKsKIEBD56BUejsECgYEA0YxX 16 | Rz+FgPAkKmr0snTTytoT40d0itaIiQfR6PdPpCPyn+WNo1NVLSoIK7+EALAJSG58 17 | HWUovvtQowmd1XCR0qETdauDTBc0yazWtOl/9XoJ3lsJxSfOpsZy6Gqi8ieoDFh3 18 | SaKnxLP9HyDeoK1QJCqHB5wNT6BGLPEsFVjSdgkCgYBVqQfJ83Tt/vH5o0jC6Rgg 19 | rg4XvYPpeUNbaAk8BCmRwMgXqbm4z2TKAhfAdckk/gB8PHYZQfN36bf+tf/XXuoH 20 | SsfBvPo9gcJklILcSdBn29cUbAlvS//d4JYj4vTC/O8Q0FYBlOj91mezrYRRj6IG 21 | UQgQPpwAWYPZePndF8yZQQKBgC4FLVHXcIF9u+OY876Ri8X8GOwMUFsBfKDjl8Ub 22 | M2FwB6P4LSAWeBlgJsU83UetYYyHvzhRdB5lYTM9NG2guFXSzExGa6J1YkF8dPbs 23 | ZQ7LS4mK4t1qvabA5JGIgdq+vNhhQWlpkIDRqqCAfoQ5K+WVdWxFaGL5ZxANs0nI 24 | 5QfJAoGAJfjIbBhpDwEuoTJUBVzriCL+xEfJY8xx1GEB/3kvz5kVSCZPwaJ7UugF 25 | EL9GbUdhBG8d7aLx/N00zTpQjTUs2Bon+rFFpNCyhNLn/RI8qwbzk6HG2iGaxoF6 26 | sE6cgyUxpGzBUgIIC59Crx95g/K1ZiwEQLf1mhMKbL+OhhJ55p8= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /deployment1/mykey.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs0ATCbuNi3vQpqSDpDtNid72/377oQ1FjIWhZX2VgouYeDOTeVWNNaw8GlKu+OR40lfcyPuVd6CZVApU0w5z1+TbqbKyTgyL3Rdy74h5qzoyuskuaSGrR5bw57T2QevpofA4GTEcj+nNMFYZ5phUIPeOieJHFLUMGeFLg75EfxVOVZ9aqtyjiED2TLfrJY4P6nSjXQmkAyn+TNBPwArkzIbo9LUoO358K5UdubVP1JOqnpsNjYbQTTmr8u4Q0MsdKEPvadwj50aPm/4adhCjUc3rX810gvK4YdXcJ5G16Gmc0WAV+0PmLEFGyCXkh2Usrb+BRMebAw7cpeN1GMfrJ suresh@suresh-Latitude-6430U 2 | -------------------------------------------------------------------------------- /deployment1/output.tf: -------------------------------------------------------------------------------- 1 | output "server-name" { 2 | value = "${openstack_compute_instance_v2.server1.name}" 3 | } 4 | output "server-private-ip" { 5 | value = "${openstack_compute_instance_v2.server1.network.0.fixed_ip_v4}" 6 | } 7 | output "server-floating-ip" { 8 | value = "${openstack_networking_floatingip_v2.fip_1.address}" 9 | } 10 | 11 | output "client1-name" { 12 | value = "${openstack_compute_instance_v2.client1.name}" 13 | } 14 | output "client1-private-ip" { 15 | value = "${openstack_compute_instance_v2.client1.network.0.fixed_ip_v4}" 16 | } 17 | output "client1-floating-ip" { 18 | value = "${openstack_networking_floatingip_v2.fip_2.address}" 19 | } 20 | 21 | output "client2-name" { 22 | value = "${openstack_compute_instance_v2.client2.name}" 23 | } 24 | output "client2-private-ip" { 25 | value = "${openstack_compute_instance_v2.client2.network.0.fixed_ip_v4}" 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /deployment1/server.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_networking_secgroup_v2" "my_secgroup" { 2 | name = "my_secgroup" 3 | description = "Allow all" 4 | } 5 | 6 | resource "openstack_networking_secgroup_rule_v2" "rule1" { 7 | direction = "ingress" 8 | ethertype = "IPv4" 9 | security_group_id = "${openstack_networking_secgroup_v2.my_secgroup.id}" 10 | } 11 | 12 | 13 | resource "openstack_compute_keypair_v2" "mykey1" { 14 | name = "mykey1" 15 | public_key = "${file("mykey.pub")}" 16 | } 17 | 18 | 19 | resource "openstack_networking_network_v2" "server_net" { 20 | name = "server_net" 21 | admin_state_up = "true" 22 | } 23 | 24 | resource "openstack_networking_subnet_v2" "server_subnet" { 25 | name = "server_subnet" 26 | network_id = "${openstack_networking_network_v2.server_net.id}" 27 | cidr = "192.168.1.0/24" 28 | } 29 | 30 | 31 | 32 | resource "openstack_networking_router_v2" "internet_router" { 33 | name = "internet_router" 34 | external_network_id = "${var.public_pool_id}" 35 | } 36 | 37 | 38 | resource "openstack_networking_router_interface_v2" "server_net_itf" { 39 | router_id = "${openstack_networking_router_v2.internet_router.id}" 40 | subnet_id = "${openstack_networking_subnet_v2.server_subnet.id}" 41 | } 42 | 43 | data "template_cloudinit_config" "init_script" { 44 | part { 45 | content_type = "text/cloud-config" 46 | content = "${file("cloudinit.yaml")}" 47 | } 48 | } 49 | 50 | 51 | resource "openstack_compute_instance_v2" "server1" { 52 | name = "server1" 53 | image_id = "${var.serverimage}" 54 | flavor_id = "${var.serverflavor}" 55 | key_pair = "${openstack_compute_keypair_v2.mykey1.name}" 56 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 57 | network { 58 | uuid = "${openstack_networking_network_v2.server_net.id}" 59 | } 60 | user_data = "${data.template_cloudinit_config.init_script.rendered}" 61 | } 62 | 63 | 64 | 65 | resource "openstack_networking_floatingip_v2" "fip_1" { 66 | pool = "public" 67 | } 68 | 69 | 70 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 71 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 72 | instance_id = "${openstack_compute_instance_v2.server1.id}" 73 | } 74 | 75 | -------------------------------------------------------------------------------- /deployment1/vars.tf: -------------------------------------------------------------------------------- 1 | variable serverimage { 2 | default = "a73ae89d-271e-45ba-8417-ddd6373dc585" 3 | } 4 | 5 | variable serverflavor { 6 | default = "d2" 7 | } 8 | 9 | 10 | variable clientimage { 11 | default = "dea87f06-9fdc-410c-974f-470b057cfa2b" 12 | } 13 | 14 | variable clientflavor { 15 | default = "1" 16 | } 17 | 18 | 19 | variable public_pool_id { 20 | default = "74736280-83bc-4ffe-8228-cbe12c091b49" 21 | } 22 | -------------------------------------------------------------------------------- /deployment2/README.md: -------------------------------------------------------------------------------- 1 | # Terraform : Project2: 2 | ================== 3 | 4 | **Objective:** 5 | 6 | I want to create multiple compute instances(identical configuration, except different cloudinit bootscripts - application provisioning ) and associate floating IPs. 7 | 8 | ![Infrastructure Diagram](deploy2.jpg?raw=true) 9 | 10 | **Technical learning:** 11 | 12 | - count parameter 13 | 14 | - element 15 | 16 | - conditional execution 17 | 18 | 19 | 20 | ### Part1 - Create Multiple compute Instances: 21 | 22 | 23 | 24 | #### 1. create a number of instances in vars.tf file 25 | 26 | ``` 27 | variable instances { 28 | type = "map" 29 | 30 | default { 31 | backend = "2" 32 | } 33 | } 34 | ``` 35 | 36 | we created a map (python terminology - its dictionary, sting keys to string values) , this can be accessed as vars.instances["backend"]. This variable will return the value 2. 37 | 38 | Reference : https://www.terraform.io/docs/configuration/variables.html#maps 39 | 40 | 41 | 42 | 43 | #### 2. In stack.tf, the openstack_compute_instance_v2 resource creation block, 44 | 45 | specify the number of resources to be created as below, 46 | 47 | ``` 48 | count = "${var.instances["backend"]}" 49 | ``` 50 | 51 | Here the count is 2. it means index 0 and 1. 52 | 53 | Reference: https://www.terraform.io/docs/configuration/resources.html#count 54 | 55 | 56 | #### 3. Access the index of the instance count. 57 | 58 | We populate the VM name from index count index. 59 | 60 | ``` 61 | name = "myvm1_${count.index}" 62 | ``` 63 | we can get the index of the count using "count.index" attribute. 64 | 65 | 66 | #### 4. conditional execution: 67 | 68 | Terraform supports the simple conditional execution to branch on the final value 69 | 70 | 71 | The conditional syntax is the well-known ternary operation: 72 | 73 | ``` 74 | CONDITION ? TRUEVAL : FALSEVAL 75 | ``` 76 | 77 | 78 | our objective is simply, run separate cloudinit for 1st server and separate one for second server. we use count.index to identify as below, 79 | 80 | 81 | ``` 82 | user_data = "${count.index > 0 ? "${data.template_cloudinit_config.init_script_2.rendered}" : "${data.template_cloudinit_config.init_script_1.rendered}"}" 83 | 84 | ``` 85 | 86 | Reference: https://www.terraform.io/docs/configuration/interpolation.html#conditionals 87 | 88 | 89 | ### Part2 - Associate the Floatingips 90 | 91 | 92 | 93 | #### 1. create a the 'n' number of floating ip resources (using count attribute) 94 | 95 | 96 | 97 | 98 | ``` 99 | resource "openstack_networking_floatingip_v2" "fip_1" { 100 | pool = "public" 101 | count = "${var.instances["backend"]}" 102 | } 103 | ``` 104 | 105 | #### 2. Associate the floating ip - using element() inbuilt funtion 106 | 107 | In earlier exercises, we use direct association of VM id and floating ip id as below, 108 | 109 | ``` 110 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 111 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 112 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 113 | } 114 | 115 | ``` 116 | 117 | But in this stack/example, we cannot access the floatingip resource id and instance id as string. Because we have used count parameters. 118 | 119 | ``` 120 | resource "openstack_networking_floatingip_v2" "fip_1" { 121 | pool = "public" 122 | count = "${var.instances["backend"]}" 123 | } 124 | ``` 125 | 126 | Hence we created multiple resources(list) on same id, The ID contains the list of resources. 127 | 128 | We can access this resources by 129 | 130 | ``` 131 | openstack_networking_floatingip_v2.fip_1.*.id 132 | ``` 133 | 134 | To access a single resource from the list of resources, **element** in-built function is used. 135 | 136 | ``` 137 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 138 | count = "${var.instances["backend"]}" 139 | floating_ip = "${element(openstack_networking_floatingip_v2.fip_1.*.address, count.index)}" 140 | instance_id = "${element(openstack_compute_instance_v2.vm1.*.id, count.index)}" 141 | } 142 | ``` 143 | 144 | 145 | Reference: 146 | 147 | https://www.terraform.io/docs/configuration/interpolation.html#element-list-index- 148 | 149 | 150 | 151 | 152 | 153 | 154 | ### References: 155 | 156 | 157 | 1. https://www.terraform.io/docs/configuration/resources.html#count 158 | 2. https://www.terraform.io/docs/configuration/interpolation.html#conditionals 159 | 3. https://www.terraform.io/docs/configuration/resources.html#using-variables-with-count 160 | 161 | -------------------------------------------------------------------------------- /deployment2/cloudinit1.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | package_update: true 4 | packages: 5 | - apache2 6 | 7 | runcmd: 8 | - sudo a2enmod ssl 9 | - sudo a2ensite default-ssl 10 | - sudo service apache2 restart 11 | 12 | final_message: "Welcome - Apache Server installed" 13 | 14 | output: 15 | final: '> /dev/ttyS0' 16 | 17 | -------------------------------------------------------------------------------- /deployment2/cloudinit2.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | package_update: true 4 | packages: 5 | - nginx 6 | 7 | runcmd: 8 | - sudo service nginx restart 9 | 10 | final_message: "Welcome - nginx Server installed" 11 | 12 | output: 13 | final: '> /dev/ttyS0' 14 | 15 | -------------------------------------------------------------------------------- /deployment2/deploy2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/learn-terraform-with-openstack/aec4f95243126956a189438c314f29b235ecc20f/deployment2/deploy2.jpg -------------------------------------------------------------------------------- /deployment2/output.tf: -------------------------------------------------------------------------------- 1 | # output vm name variable 2 | 3 | output "vm-name" { 4 | value = "${openstack_compute_instance_v2.vm1.*.name}" 5 | } 6 | 7 | # output vm-id variable 8 | 9 | output "vm-id" { 10 | value = "${openstack_compute_instance_v2.vm1.*.id}" 11 | } 12 | 13 | 14 | 15 | # output vm-ip variable 16 | 17 | output "vm-ip" { 18 | value = "${openstack_compute_instance_v2.vm1.*.network.0.fixed_ip_v4}" 19 | } 20 | 21 | output "floating-ips" { 22 | value = "${openstack_networking_floatingip_v2.fip_1.*.address}" 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /deployment2/stack.tf: -------------------------------------------------------------------------------- 1 | # Below resources in stack.tf file 2 | 3 | resource "openstack_networking_secgroup_v2" "my_secgroup" { 4 | name = "my_secgroup" 5 | description = "Allow all" 6 | } 7 | 8 | resource "openstack_networking_secgroup_rule_v2" "rule1" { 9 | direction = "ingress" 10 | ethertype = "IPv4" 11 | security_group_id = "${openstack_networking_secgroup_v2.my_secgroup.id}" 12 | } 13 | 14 | resource "openstack_networking_network_v2" "client_net" { 15 | name = "client_net" 16 | admin_state_up = "true" 17 | } 18 | 19 | resource "openstack_networking_subnet_v2" "client_subnet" { 20 | name = "client_subnet" 21 | network_id = "${openstack_networking_network_v2.client_net.id}" 22 | cidr = "172.1.1.0/24" 23 | } 24 | 25 | 26 | resource "openstack_networking_router_v2" "myrouter" { 27 | name = "myrouter" 28 | external_network_id = "${var.public_pool_id}" 29 | } 30 | 31 | resource "openstack_networking_router_interface_v2" "client_net_itf" { 32 | router_id = "${openstack_networking_router_v2.myrouter.id}" 33 | subnet_id = "${openstack_networking_subnet_v2.client_subnet.id}" 34 | } 35 | 36 | 37 | resource "openstack_compute_instance_v2" "vm1" { 38 | name = "myvm1_${count.index}" 39 | image_id = "${var.myimage}" 40 | flavor_id = "${var.myflavor}" 41 | key_pair = "${var.mykey}" 42 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 43 | count = "${var.instances["backend"]}" 44 | 45 | network { 46 | uuid = "${openstack_networking_network_v2.client_net.id}" 47 | } 48 | 49 | #user_data = "${data.template_cloudinit_config.init_script_2.rendered}" 50 | #conditional execution of cloudinit script 51 | 52 | user_data = "${count.index > 0 ? "${data.template_cloudinit_config.init_script_2.rendered}" : "${data.template_cloudinit_config.init_script_1.rendered}"}" 53 | 54 | } 55 | 56 | 57 | 58 | data "template_cloudinit_config" "init_script_1" { 59 | part { 60 | content_type = "text/cloud-config" 61 | content = "${file("cloudinit1.yaml")}" 62 | } 63 | } 64 | 65 | data "template_cloudinit_config" "init_script_2" { 66 | part { 67 | content_type = "text/cloud-config" 68 | content = "${file("cloudinit2.yaml")}" 69 | } 70 | } 71 | 72 | 73 | resource "openstack_networking_floatingip_v2" "fip_1" { 74 | pool = "public" 75 | count = "${var.instances["backend"]}" 76 | } 77 | 78 | 79 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 80 | count = "${var.instances["backend"]}" 81 | floating_ip = "${element(openstack_networking_floatingip_v2.fip_1.*.address, count.index)}" 82 | instance_id = "${element(openstack_compute_instance_v2.vm1.*.id, count.index)}" 83 | } 84 | 85 | -------------------------------------------------------------------------------- /deployment2/vars.tf: -------------------------------------------------------------------------------- 1 | # Below variables in vars.tf file 2 | 3 | provider "openstack" { 4 | user_name = "demo" 5 | tenant_name = "demo" 6 | password = "openstack123" 7 | auth_url = "http://10.0.1.4/identity" 8 | region = "RegionOne" 9 | domain_name = "default" 10 | } 11 | 12 | 13 | variable myimage { 14 | default = "2e0794ad-eb68-49a2-82b7-94a6b197a5ce" 15 | } 16 | 17 | variable myflavor { 18 | default = "7" 19 | } 20 | 21 | variable public_pool_id { 22 | default = "88c7bdb2-a1e4-4c0e-8263-c6b4eccb8072" 23 | } 24 | 25 | 26 | variable mykey { 27 | default = "mykey" 28 | } 29 | 30 | variable instances { 31 | type = "map" 32 | 33 | default { 34 | backend = "2" 35 | } 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /exercises/cloudinit.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | package_update: true 3 | packages: 4 | - apache2 5 | runcmd: 6 | - sudo a2enmod ssl 7 | - sudo a2ensite default-ssl 8 | - sudo service apache2 restart 9 | - echo `hostname` | sudo tee /var/www/html/index.html 10 | output: 11 | final: '> /dev/ttyS0' 12 | -------------------------------------------------------------------------------- /exercises/ex1.tf: -------------------------------------------------------------------------------- 1 | /* 2 | Exercise 1: 3 | 4 | Objective: 5 | Create a instance in openstack, with existing image, flavor, keypair, security-group and network resources. 6 | 7 | Use terraform provider and resource block. 8 | 9 | */ 10 | 11 | 12 | # Provider details 13 | 14 | provider "openstack" { 15 | user_name = "demo" 16 | tenant_name = "demo" 17 | password = "openstack123" 18 | auth_url = "http://10.0.1.6/identity" 19 | region = "RegionOne" 20 | domain_name = "default" 21 | } 22 | 23 | # Instance creation 24 | 25 | resource "openstack_compute_instance_v2" "vm1" { 26 | name = "vm1" 27 | image_id = "dea87f06-9fdc-410c-974f-470b057cfa2b" 28 | flavor_id = "1" 29 | key_pair = "mykey" 30 | security_groups = ["default"] 31 | network { 32 | uuid = "db4a268a-465d-40d7-9db2-54b82d945bec" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /exercises/ex10.tf: -------------------------------------------------------------------------------- 1 | provider "openstack" { 2 | user_name = "admin" 3 | tenant_name = "admin" 4 | password = "openstack123" 5 | auth_url = "http://10.0.1.6/identity" 6 | region = "RegionOne" 7 | domain_name = "default" 8 | } 9 | 10 | resource "openstack_images_image_v2" "ubuntu" { 11 | name = "ubuntu16" 12 | image_source_url = "https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img" 13 | container_format = "bare" 14 | disk_format = "qcow2" 15 | visibility = "public" 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /exercises/ex1a.tf: -------------------------------------------------------------------------------- 1 | /* 2 | Objective: 3 | Create a instance in openstack, with existing image, flavor, keypair, security-group and network resources. 4 | 5 | Using output block to display the output of ID, name and fixed IP parameters. 6 | 7 | */ 8 | 9 | 10 | # Provider details 11 | 12 | provider "openstack" { 13 | user_name = "demo" 14 | tenant_name = "demo" 15 | password = "openstack123" 16 | auth_url = "http://10.0.1.6/identity" 17 | region = "RegionOne" 18 | domain_name = "default" 19 | } 20 | 21 | # Instance creation 22 | 23 | resource "openstack_compute_instance_v2" "vm1" { 24 | name = "vm1" 25 | image_id = "dea87f06-9fdc-410c-974f-470b057cfa2b" 26 | flavor_id = "1" 27 | key_pair = "mykey" 28 | security_groups = ["default"] 29 | network { 30 | uuid = "db4a268a-465d-40d7-9db2-54b82d945bec" 31 | } 32 | } 33 | 34 | # output vm name variable 35 | 36 | output "vm-name" { 37 | value = "${openstack_compute_instance_v2.vm1.name}" 38 | } 39 | 40 | # output vm-id variable 41 | 42 | output "vm-id" { 43 | value = "${openstack_compute_instance_v2.vm1.id}" 44 | } 45 | 46 | # output vm-ip variable 47 | 48 | output "vm-ip" { 49 | value = "${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4}" 50 | } 51 | 52 | -------------------------------------------------------------------------------- /exercises/ex2.tf: -------------------------------------------------------------------------------- 1 | /* 2 | Objective: 3 | Create a instance in openstack, with existing image, flavor, keypair, security-group and network resources. 4 | Create a floating IP, and associate with the VM. 5 | 6 | Using output block to display the output of ID, name and fixed IP parameters. 7 | 8 | */ 9 | 10 | 11 | # Provider details 12 | 13 | provider "openstack" { 14 | user_name = "demo" 15 | tenant_name = "demo" 16 | password = "openstack123" 17 | auth_url = "http://10.0.1.6/identity" 18 | region = "RegionOne" 19 | domain_name = "default" 20 | } 21 | 22 | 23 | 24 | variable myimage { 25 | default = "dea87f06-9fdc-410c-974f-470b057cfa2b" 26 | } 27 | 28 | variable myflavor { 29 | default = "1" 30 | } 31 | 32 | variable mykey { 33 | default = "mykey" 34 | } 35 | 36 | variable mysecgroup { 37 | default = "default" 38 | } 39 | 40 | 41 | 42 | # Instance creation 43 | 44 | resource "openstack_compute_instance_v2" "vm1" { 45 | name = "vm1" 46 | image_id = "${var.myimage}" 47 | flavor_id = "${var.myflavor}" 48 | key_pair = "${var.mykey}" 49 | security_groups = ["${var.mysecgroup}"] 50 | network { 51 | uuid = "db4a268a-465d-40d7-9db2-54b82d945bec" 52 | } 53 | } 54 | 55 | resource "openstack_networking_floatingip_v2" "fip_1" { 56 | pool = "public" 57 | } 58 | 59 | 60 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 61 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 62 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 63 | } 64 | 65 | 66 | # output vm name variable 67 | 68 | output "vm-name" { 69 | value = "${openstack_compute_instance_v2.vm1.name}" 70 | } 71 | 72 | # output vm-id variable 73 | 74 | output "vm-id" { 75 | value = "${openstack_compute_instance_v2.vm1.id}" 76 | } 77 | 78 | # output vm-ip variable 79 | 80 | output "vm-ip" { 81 | value = "${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4}" 82 | } 83 | 84 | # output floating-ip variable 85 | 86 | output "vm-floating-ip" { 87 | value = "${openstack_networking_floatingip_v2.fip_1.address}" 88 | } -------------------------------------------------------------------------------- /exercises/ex3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/learn-terraform-with-openstack/aec4f95243126956a189438c314f29b235ecc20f/exercises/ex3.png -------------------------------------------------------------------------------- /exercises/ex3.tf: -------------------------------------------------------------------------------- 1 | 2 | # Below variables in vars.tf file 3 | 4 | variable myimage { 5 | default = "a73ae89d-271e-45ba-8417-ddd6373dc585" 6 | } 7 | 8 | variable myflavor { 9 | default = "d2" 10 | } 11 | 12 | variable public_pool_id { 13 | default = "74736280-83bc-4ffe-8228-cbe12c091b49" 14 | } 15 | 16 | 17 | 18 | # Below resources in stack.tf file 19 | 20 | resource "openstack_networking_secgroup_v2" "my_secgroup" { 21 | name = "my_secgroup" 22 | description = "Allow all" 23 | } 24 | 25 | resource "openstack_networking_secgroup_rule_v2" "rule1" { 26 | direction = "ingress" 27 | ethertype = "IPv4" 28 | security_group_id = "${openstack_networking_secgroup_v2.my_secgroup.id}" 29 | } 30 | 31 | 32 | resource "openstack_compute_keypair_v2" "mykey1" { 33 | name = "mykey1" 34 | public_key = "${file("testkey.pub")}" 35 | } 36 | 37 | 38 | resource "openstack_networking_network_v2" "client_net" { 39 | name = "client_net" 40 | admin_state_up = "true" 41 | } 42 | 43 | resource "openstack_networking_subnet_v2" "client_subnet" { 44 | name = "client_subnet" 45 | network_id = "${openstack_networking_network_v2.client_net.id}" 46 | cidr = "172.1.1.0/24" 47 | } 48 | 49 | 50 | resource "openstack_networking_router_v2" "myrouter" { 51 | name = "myrouter" 52 | external_network_id = "${var.public_pool_id}" 53 | } 54 | 55 | resource "openstack_networking_router_interface_v2" "client_net_itf" { 56 | router_id = "${openstack_networking_router_v2.myrouter.id}" 57 | subnet_id = "${openstack_networking_subnet_v2.client_subnet.id}" 58 | } 59 | 60 | 61 | resource "openstack_compute_instance_v2" "vm1" { 62 | name = "vm1" 63 | image_id = "${var.myimage}" 64 | flavor_id = "${var.myflavor}" 65 | key_pair = "${openstack_compute_keypair_v2.mykey1.name}" 66 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 67 | network { 68 | uuid = "${openstack_networking_network_v2.client_net.id}" 69 | } 70 | } 71 | 72 | 73 | resource "openstack_networking_floatingip_v2" "fip_1" { 74 | pool = "public" 75 | } 76 | 77 | 78 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 79 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 80 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 81 | } 82 | 83 | 84 | 85 | # output vm name variable 86 | 87 | output "vm-name" { 88 | value = "${openstack_compute_instance_v2.vm1.name}" 89 | } 90 | 91 | # output vm-id variable 92 | 93 | output "vm-id" { 94 | value = "${openstack_compute_instance_v2.vm1.id}" 95 | } 96 | 97 | # output vm-ip variable 98 | 99 | output "vm-ip" { 100 | value = "${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4}" 101 | } 102 | 103 | # output floating-ip variable 104 | 105 | output "vm-floating-ip" { 106 | value = "${openstack_networking_floatingip_v2.fip_1.address}" 107 | } -------------------------------------------------------------------------------- /exercises/ex4.tf: -------------------------------------------------------------------------------- 1 | # use ex3.tf and update this 2 | 3 | data "template_cloudinit_config" "init_script" { 4 | part { 5 | content_type = "text/cloud-config" 6 | content = "${file("cloudinit.yaml")}" 7 | } 8 | } 9 | 10 | 11 | 12 | resource "openstack_compute_instance_v2" "vm1" { 13 | name = "vm1" 14 | image_id = "${var.myimage}" 15 | flavor_id = "${var.myflavor}" 16 | key_pair = "${openstack_compute_keypair_v2.mykey1.name}" 17 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 18 | network { 19 | uuid = "${openstack_networking_network_v2.client_net.id}" 20 | } 21 | user_data = "${data.template_cloudinit_config.init_script.rendered}" 22 | } 23 | -------------------------------------------------------------------------------- /exercises/mykey: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEArNAEwm7jYt70Kakg6Q7TYne9v9++6ENRYyFoWV9lYKLmHgzk 3 | 3lVjTWsPBpSrvjkeNJX3Mj7lXegmVQKVNMOc9fk26mysk4Mi90Xcu+Ieas6MrrJL 4 | mkhq0eW8Oe09kHr6aHwOBkxHI/pzTBWGeaYVCD3joniRxS1DBnhS4O+RH8VTlWfW 5 | qrco4hA9ky36yWOD+p0o10JpAMp/kzQT8AK5MyG6PS1KDt+fCuVHbm1T9STqp6bD 6 | Y2G0E05q/LuENDLHShD72ncI+dGj5v+GnYQo1HN61/NdILyuGHV3CeRtehpnNFgF 7 | ftD5ixBRsgl5IdlLK2/gUTHmwMO3KXjdRjH6yQIDAQABAoIBAB8o7wLEDdohC3OL 8 | nHSJiNIDd0JmrLyijsVKG8+ppNT06ntWpdn1GY+3EyGDoygMkoa217jGoIL7PhYr 9 | /g1ijCXKBv3kFIYQqjhd73wtPIDTt4g0e+9YyXIJc5QaU/R+SDKY08qM7HLvUOTS 10 | KMo8iSRQTIBaLyaXj7NV9NO8PrW0ihCJ+ktvngrTBpAh3mGyxGXtaqPw0fFiagr9 11 | 84gyy0eQcehU+4GXiPzPumWOL8NbAtp/d7l4QG+7HdQwj+cjARxadD+8KyxvkbK3 12 | Lidw3Z9DYz90CYzsXiQFQ+KErOcNTikNE4vmZ90ILvTiF1VJbprDn2WtDx0uCxWW 13 | GuiaZgECgYEA0x73PSyhj3SYnitxOo/D3Zf+cDtDLeecxJ9bhwRvJ/xSJQFyozt2 14 | zhJT/nl0VZkPR+VzehqPIzzfZXtDjH+r9JvqNXBNbXP1x3BHLD53/eJlOWFDbtV3 15 | 1H0nwXi0NB6OwF4HPSvRxt2dzVpQVzkYe1YLAbXkKsKIEBD56BUejsECgYEA0YxX 16 | Rz+FgPAkKmr0snTTytoT40d0itaIiQfR6PdPpCPyn+WNo1NVLSoIK7+EALAJSG58 17 | HWUovvtQowmd1XCR0qETdauDTBc0yazWtOl/9XoJ3lsJxSfOpsZy6Gqi8ieoDFh3 18 | SaKnxLP9HyDeoK1QJCqHB5wNT6BGLPEsFVjSdgkCgYBVqQfJ83Tt/vH5o0jC6Rgg 19 | rg4XvYPpeUNbaAk8BCmRwMgXqbm4z2TKAhfAdckk/gB8PHYZQfN36bf+tf/XXuoH 20 | SsfBvPo9gcJklILcSdBn29cUbAlvS//d4JYj4vTC/O8Q0FYBlOj91mezrYRRj6IG 21 | UQgQPpwAWYPZePndF8yZQQKBgC4FLVHXcIF9u+OY876Ri8X8GOwMUFsBfKDjl8Ub 22 | M2FwB6P4LSAWeBlgJsU83UetYYyHvzhRdB5lYTM9NG2guFXSzExGa6J1YkF8dPbs 23 | ZQ7LS4mK4t1qvabA5JGIgdq+vNhhQWlpkIDRqqCAfoQ5K+WVdWxFaGL5ZxANs0nI 24 | 5QfJAoGAJfjIbBhpDwEuoTJUBVzriCL+xEfJY8xx1GEB/3kvz5kVSCZPwaJ7UugF 25 | EL9GbUdhBG8d7aLx/N00zTpQjTUs2Bon+rFFpNCyhNLn/RI8qwbzk6HG2iGaxoF6 26 | sE6cgyUxpGzBUgIIC59Crx95g/K1ZiwEQLf1mhMKbL+OhhJ55p8= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /exercises/mykey.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs0ATCbuNi3vQpqSDpDtNid72/377oQ1FjIWhZX2VgouYeDOTeVWNNaw8GlKu+OR40lfcyPuVd6CZVApU0w5z1+TbqbKyTgyL3Rdy74h5qzoyuskuaSGrR5bw57T2QevpofA4GTEcj+nNMFYZ5phUIPeOieJHFLUMGeFLg75EfxVOVZ9aqtyjiED2TLfrJY4P6nSjXQmkAyn+TNBPwArkzIbo9LUoO358K5UdubVP1JOqnpsNjYbQTTmr8u4Q0MsdKEPvadwj50aPm/4adhCjUc3rX810gvK4YdXcJ5G16Gmc0WAV+0PmLEFGyCXkh2Usrb+BRMebAw7cpeN1GMfrJ suresh@suresh-Latitude-6430U 2 | -------------------------------------------------------------------------------- /lbaas/README.md: -------------------------------------------------------------------------------- 1 | # Loadbalancer: 2 | 3 | **Objective:** 4 | 5 | Demonstrate the Openstack Load balancer functionality with stack. 6 | 7 | **configuration** 8 | 9 | Two Webservers in the backend 10 | Loadbalancer(with Round robin algorithm) 11 | Backend servers are member of this loadbalancer. 12 | Floating IP/Public IP is associated to the loadbalancer. 13 | 14 | ![Infrastructure Diagram](lbaas.jpg?raw=true) 15 | 16 | 17 | **User Demo:** 18 | 19 | http request to the FloatingIP of the loadbalancer. User gets the Response from the backend servers. 20 | 21 | 22 | **Technical learning:** 23 | 24 | load balancer resources 25 | 26 | 27 | **openstack commands** 28 | 29 | - neutron lbaas-loadbalancer-list 30 | - neutron lbaas-listener-list 31 | - neutron lbaas-pool-list 32 | - neutron lbaas-member-list 33 | - neutron lbaas-healthmonitor-list 34 | 35 | Reference: 36 | https://docs.openstack.org/mitaka/networking-guide/config-lbaas.html 37 | 38 | 39 | **Terraform resources** 40 | 41 | - openstack_lb_loadbalancer_v2 42 | - openstack_lb_listener_v2 43 | - openstack_lb_pool_v2 44 | - openstack_lb_member_v2 45 | - openstack_lb_monitor_v2 46 | 47 | Reference: 48 | https://www.terraform.io/docs/providers/openstack/r/lb_loadbalancer_v2.html 49 | 50 | 51 | 52 | 53 | 54 | 55 | ### Part1 - Create a backend servers 56 | 57 | Lets use the old stack . 58 | 59 | 60 | ### Part2 - Create a LBAAS resources 61 | 62 | 63 | #### openstack_lb_loadbalancer_v2 64 | 65 | 66 | ``` 67 | resource "openstack_lb_loadbalancer_v2" "mylb" { 68 | name = "mylb" 69 | vip_subnet_id = "${openstack_networking_subnet_v2.backend_subnet.id}" 70 | security_group_ids = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 71 | } 72 | 73 | ``` 74 | 75 | 76 | #### openstack_lb_listener_v2 77 | 78 | 79 | ``` 80 | resource "openstack_lb_listener_v2" "mylistener" { 81 | name = "mylistener" 82 | loadbalancer_id = "${openstack_lb_loadbalancer_v2.mylb.id}" 83 | protocol = "HTTP" 84 | protocol_port = "80" 85 | } 86 | ``` 87 | 88 | 89 | 90 | 91 | #### openstack_lb_pool_v2 92 | 93 | 94 | ``` 95 | resource "openstack_lb_pool_v2" "mypool" { 96 | name = "mypool" 97 | lb_method = "ROUND_ROBIN" 98 | protocol = "HTTP" 99 | listener_id = "${openstack_lb_listener_v2.mylistener.id}" 100 | } 101 | ``` 102 | 103 | 104 | #### openstack_lb_member_v2 105 | 106 | Here we associate our backend servers to the lbaas. 107 | 108 | ``` 109 | resource "openstack_lb_member_v2" "member_1" { 110 | address = "${element(openstack_compute_instance_v2.server.*.network.0.fixed_ip_v4, count.index)}" 111 | count = "${var.instances["backend"]}" 112 | subnet_id = "${openstack_networking_subnet_v2.backend_subnet.id}" 113 | protocol_port = "80" 114 | pool_id = "${openstack_lb_pool_v2.mypool.id}" 115 | } 116 | ``` 117 | 118 | #### openstack_lb_monitor_v2 119 | 120 | 121 | 122 | ``` 123 | resource "openstack_lb_monitor_v2" "monitor_1" { 124 | pool_id = "${openstack_lb_pool_v2.mypool.id}" 125 | type = "PING" 126 | delay = 10 127 | timeout = 5 128 | max_retries = 3 129 | url_path = "/index.html" 130 | expected_codes = "200" 131 | admin_state_up = "true" 132 | } 133 | ``` 134 | 135 | 136 | #### Associate the floating ip to the LBAAS vip port: 137 | 138 | ``` 139 | resource "openstack_networking_floatingip_v2" "fip_vip" { 140 | pool = "public" 141 | port_id = "${openstack_lb_loadbalancer_v2.mylb.vip_port_id}" 142 | } 143 | ``` 144 | 145 | 146 | ### Part3 - Deploy the stack & Testing 147 | 148 | **Deploy** 149 | 150 | ``` 151 | terraform init 152 | terraform plan 153 | terraform apply -parallelism=1 154 | ``` 155 | 156 | **Testing** 157 | 158 | ``` 159 | curl 160 | ``` 161 | 162 | ### References: 163 | 164 | 1. https://docs.openstack.org/mitaka/networking-guide/config-lbaas.html 165 | 2. https://www.terraform.io/docs/providers/openstack/r/lb_loadbalancer_v2.html 166 | 167 | -------------------------------------------------------------------------------- /lbaas/cloudinit1.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | package_update: true 4 | packages: 5 | - apache2 6 | 7 | runcmd: 8 | - sudo a2enmod ssl 9 | - sudo a2ensite default-ssl 10 | - sudo service apache2 restart 11 | 12 | final_message: "Welcome - Apache Server installed" 13 | 14 | output: 15 | final: '> /dev/ttyS0' 16 | 17 | -------------------------------------------------------------------------------- /lbaas/cloudinit2.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | package_update: true 4 | packages: 5 | - nginx 6 | 7 | runcmd: 8 | - sudo service nginx restart 9 | 10 | final_message: "Welcome - nginx Server installed" 11 | 12 | output: 13 | final: '> /dev/ttyS0' 14 | 15 | -------------------------------------------------------------------------------- /lbaas/lbaas.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knetsolutions/learn-terraform-with-openstack/aec4f95243126956a189438c314f29b235ecc20f/lbaas/lbaas.jpg -------------------------------------------------------------------------------- /lbaas/output.tf: -------------------------------------------------------------------------------- 1 | # output vm name variable 2 | output "vm-name" { 3 | value = "${openstack_compute_instance_v2.server.*.name}" 4 | } 5 | 6 | # output vm-id variable 7 | 8 | output "vm-id" { 9 | value = "${openstack_compute_instance_v2.server.*.id}" 10 | } 11 | 12 | 13 | 14 | # output vm-ip variable 15 | 16 | output "vm-ip" { 17 | value = "${openstack_compute_instance_v2.server.*.network.0.fixed_ip_v4}" 18 | } 19 | 20 | 21 | 22 | output "vip_ip" { 23 | value = "${openstack_networking_floatingip_v2.fip_vip.address}" 24 | } 25 | 26 | output "backends_ip" { 27 | value = ["${openstack_lb_member_v2.member_1.*.address}"] 28 | } 29 | 30 | -------------------------------------------------------------------------------- /lbaas/stack.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "openstack_networking_secgroup_v2" "my_secgroup" { 3 | name = "my_secgroup" 4 | description = "Allow all" 5 | } 6 | 7 | resource "openstack_networking_secgroup_rule_v2" "rule1" { 8 | direction = "ingress" 9 | ethertype = "IPv4" 10 | security_group_id = "${openstack_networking_secgroup_v2.my_secgroup.id}" 11 | } 12 | 13 | resource "openstack_networking_network_v2" "backend_net" { 14 | name = "backend_net" 15 | admin_state_up = "true" 16 | } 17 | 18 | resource "openstack_networking_subnet_v2" "backend_subnet" { 19 | name = "backend_subnet" 20 | network_id = "${openstack_networking_network_v2.backend_net.id}" 21 | cidr = "10.10.10.0/24" 22 | } 23 | 24 | 25 | resource "openstack_networking_router_v2" "myrouter" { 26 | name = "myrouter" 27 | external_network_id = "${var.public_pool_id}" 28 | } 29 | 30 | resource "openstack_networking_router_interface_v2" "backend_net_itf" { 31 | router_id = "${openstack_networking_router_v2.myrouter.id}" 32 | subnet_id = "${openstack_networking_subnet_v2.backend_subnet.id}" 33 | } 34 | 35 | 36 | resource "openstack_compute_instance_v2" "server" { 37 | name = "myvm1_${count.index}" 38 | image_id = "${var.myimage}" 39 | flavor_id = "${var.myflavor}" 40 | key_pair = "${var.mykey}" 41 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 42 | count = "${var.instances["backend"]}" 43 | 44 | network { 45 | uuid = "${openstack_networking_network_v2.backend_net.id}" 46 | } 47 | 48 | #user_data = "${data.template_cloudinit_config.init_script_2.rendered}" 49 | #conditional execution of cloudinit script 50 | 51 | user_data = "${count.index > 0 ? "${data.template_cloudinit_config.init_script_2.rendered}" : "${data.template_cloudinit_config.init_script_1.rendered}"}" 52 | } 53 | 54 | 55 | 56 | data "template_cloudinit_config" "init_script_1" { 57 | part { 58 | content_type = "text/cloud-config" 59 | content = "${file("cloudinit1.yaml")}" 60 | } 61 | } 62 | 63 | data "template_cloudinit_config" "init_script_2" { 64 | part { 65 | content_type = "text/cloud-config" 66 | content = "${file("cloudinit2.yaml")}" 67 | } 68 | } 69 | 70 | 71 | 72 | /* 73 | 74 | Lbaas resources starts from here 75 | 76 | */ 77 | 78 | 79 | resource "openstack_lb_loadbalancer_v2" "mylb" { 80 | name = "mylb" 81 | vip_subnet_id = "${openstack_networking_subnet_v2.backend_subnet.id}" 82 | security_group_ids = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 83 | } 84 | 85 | 86 | resource "openstack_lb_listener_v2" "mylistener" { 87 | name = "mylistener" 88 | loadbalancer_id = "${openstack_lb_loadbalancer_v2.mylb.id}" 89 | protocol = "HTTP" 90 | protocol_port = "80" 91 | } 92 | 93 | resource "openstack_lb_pool_v2" "mypool" { 94 | name = "mypool" 95 | lb_method = "ROUND_ROBIN" 96 | protocol = "HTTP" 97 | listener_id = "${openstack_lb_listener_v2.mylistener.id}" 98 | #region = "${var.region}" 99 | } 100 | 101 | resource "openstack_lb_member_v2" "member_1" { 102 | address = "${element(openstack_compute_instance_v2.server.*.network.0.fixed_ip_v4, count.index)}" 103 | count = "${var.instances["backend"]}" 104 | subnet_id = "${openstack_networking_subnet_v2.backend_subnet.id}" 105 | protocol_port = "80" 106 | pool_id = "${openstack_lb_pool_v2.mypool.id}" 107 | } 108 | 109 | resource "openstack_lb_monitor_v2" "monitor_1" { 110 | pool_id = "${openstack_lb_pool_v2.mypool.id}" 111 | type = "PING" 112 | delay = 10 113 | timeout = 5 114 | max_retries = 3 115 | url_path = "/index.html" 116 | expected_codes = "200" 117 | admin_state_up = "true" 118 | } 119 | 120 | resource "openstack_networking_floatingip_v2" "fip_vip" { 121 | pool = "public" 122 | port_id = "${openstack_lb_loadbalancer_v2.mylb.vip_port_id}" 123 | } 124 | -------------------------------------------------------------------------------- /lbaas/vars.tf: -------------------------------------------------------------------------------- 1 | # Below variables in vars.tf file 2 | 3 | provider "openstack" { 4 | user_name = "demo" 5 | tenant_name = "demo" 6 | password = "openstack123" 7 | auth_url = "http://10.0.1.3/identity" 8 | region = "RegionOne" 9 | domain_name = "default" 10 | } 11 | 12 | 13 | variable myimage { 14 | default = "cead651c-3cf4-424e-a7a4-722ceea5424f" 15 | } 16 | 17 | variable myflavor { 18 | default = "7" 19 | } 20 | 21 | variable public_pool_id { 22 | default = "8c56b2e0-7db7-46db-bf4e-8efec5b87737" 23 | } 24 | 25 | 26 | variable mykey { 27 | default = "testkey" 28 | } 29 | 30 | variable instances { 31 | type = "map" 32 | 33 | default { 34 | backend = "2" 35 | } 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /provisioner/README.md: -------------------------------------------------------------------------------- 1 | # Provisioner 2 | 3 | 4 | Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction. 5 | 6 | Provisioners can be used to bootstrap a resource, cleanup before destroy, run configuration management, etc. 7 | 8 | Provisioners are added directly to any resource. 9 | 10 | 11 | Reference: 12 | https://www.terraform.io/docs/provisioners/index.html 13 | 14 | 15 | ## Types / classifications: 16 | 17 | 1. local-exec 18 | 2. remote-exec 19 | 3. file 20 | 4. connection block 21 | 5. null-resource 22 | 6. chef 23 | 7. habitat 24 | 8. salt-masterless 25 | 26 | 27 | ## 1.local-exec provisioner 28 | 29 | The local-exec provisioner invokes a local executable after a resource is created. This invokes a process on the machine running Terraform, not on the resource. 30 | 31 | 32 | It must be inside a resource. 33 | 34 | syntax : 35 | 36 | ``` 37 | provisioner "local-exec" { 38 | command = "shell command or executable" 39 | } 40 | 41 | ``` 42 | 43 | **Example:** 44 | 45 | ``` 46 | resource "openstack_compute_instance_v2" "vm1" { 47 | name = "vm1" 48 | image_id = "${var.myimage}" 49 | flavor_id = "${var.myflavor}" 50 | key_pair = "${var.mykey}" 51 | security_groups = ["${var.mysg}"] 52 | network { 53 | uuid = "${openstack_networking_network_v2.client_net.id}" 54 | } 55 | 56 | provisioner "local-exec" { 57 | command = "echo ${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4} >> vm_ips.txt" 58 | } 59 | } 60 | 61 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 62 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 63 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 64 | 65 | provisioner "local-exec" { 66 | command = "ping ${openstack_networking_floatingip_v2.fip_1.address} -c 25" 67 | } 68 | 69 | } 70 | 71 | ``` 72 | Note: example is located in provisioner directory prov_ex1.tf file. 73 | 74 | 75 | 76 | 77 | ## 2.remote-exec provisioner 78 | 79 | 80 | The remote-exec provisioner invokes a script on a remote resource after it is created. This can be used to run a configuration management tool, bootstrap into a cluster, etc. 81 | 82 | The remote-exec provisioner supports both ssh and winrm type connections. 83 | 84 | Reference: https://www.terraform.io/docs/provisioners/remote-exec.html 85 | 86 | 87 | 88 | **connection block** contains connecting information(ssh), used by provisioners. 89 | Example: 90 | ``` 91 | connection { 92 | type = "ssh" 93 | user = "cirros" 94 | password = "cubswin:)" 95 | host = "${openstack_networking_floatingip_v2.fip_1.address}" 96 | } 97 | ``` 98 | 99 | 100 | remote-exec provisioner supports two types of actions. 101 | 102 | 1. provides the inline commands to run in the remote machine 103 | 2. provides the script, which will be copied to remote machine and execute it. 104 | 105 | 106 | **remote-exec provisioner - inline commands:** 107 | 108 | ``` 109 | provisioner "remote-exec" { 110 | inline = [ 111 | "ping -c 4 8.8.8.8 > /tmp/results.txt" 112 | ] 113 | 114 | connection { 115 | type = "ssh" 116 | user = "cirros" 117 | password = "cubswin:)" 118 | host = "${openstack_networking_floatingip_v2.fip_1.address}" 119 | } 120 | } 121 | ``` 122 | 123 | **remote-exec provisioner - script:** 124 | 125 | ``` 126 | provisioner "remote-exec" { 127 | script = "test.sh" 128 | 129 | connection { 130 | type = "ssh" 131 | user = "cirros" 132 | password = "cubswin:)" 133 | host = "${openstack_networking_floatingip_v2.fip_1.address}" 134 | } 135 | } 136 | ``` 137 | 138 | ## 3. file provisioner 139 | 140 | 141 | The file provisioner is used to copy files or directories from the machine executing Terraform to the newly created resource. 142 | 143 | Reference: https://www.terraform.io/docs/provisioners/file.html 144 | 145 | 146 | ``` 147 | provisioner "file" { 148 | source = "test.txt" 149 | destination = "/tmp/test.txt" 150 | 151 | connection { 152 | type = "ssh" 153 | user = "cirros" 154 | password = "cubswin:)" 155 | host = "${openstack_networking_floatingip_v2.fip_1.address}" 156 | } 157 | } 158 | ``` 159 | 160 | 161 | ## 4. null resource 162 | 163 | The null_resource is a resource that allows you to configure provisioners that are not directly associated with a single existing resource. 164 | 165 | Basically we want to use provisioner(execute someaction) independently not part of any existing resource. 166 | 167 | we can use "depends_on" attribute, to specify the dependency of the null resource. 168 | 169 | 170 | ``` 171 | resource "null_resource" "ping_floatingip" { 172 | 173 | depends_on = ["openstack_compute_instance_v2.vm1"] 174 | 175 | provisioner "local-exec" { 176 | command = "ping ${openstack_networking_floatingip_v2.fip_1.address} -c 10" 177 | } 178 | } 179 | ``` 180 | 181 | Here we use Null resource to ping the floating ip (from local machine/provisioner) , the dependency of exeuction of Null rresource is completion of compute instance creation. 182 | 183 | -------------------------------------------------------------------------------- /provisioner/file_prov/prov_ex3.tf: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ******File Provisioner exercise.***** 4 | 5 | 6 | How to run: 7 | terraform apply -parallelism=1 8 | */ 9 | 10 | 11 | 12 | resource "openstack_networking_network_v2" "client_net" { 13 | name = "client_net" 14 | admin_state_up = "true" 15 | } 16 | 17 | resource "openstack_networking_subnet_v2" "client_subnet" { 18 | name = "client_subnet" 19 | network_id = "${openstack_networking_network_v2.client_net.id}" 20 | cidr = "10.10.10.0/24" 21 | } 22 | 23 | 24 | resource "openstack_networking_router_v2" "myrouter" { 25 | name = "myrouter" 26 | external_network_id = "${var.public_pool_id}" 27 | } 28 | 29 | resource "openstack_networking_router_interface_v2" "client_net_itf" { 30 | router_id = "${openstack_networking_router_v2.myrouter.id}" 31 | subnet_id = "${openstack_networking_subnet_v2.client_subnet.id}" 32 | } 33 | 34 | 35 | resource "openstack_compute_instance_v2" "vm1" { 36 | name = "vm1" 37 | image_id = "${var.mycimage}" 38 | flavor_id = "${var.myflavor}" 39 | key_pair = "${var.mykey}" 40 | security_groups = ["${var.mysg}"] 41 | network { 42 | uuid = "${openstack_networking_network_v2.client_net.id}" 43 | } 44 | 45 | provisioner "local-exec" { 46 | command = "echo ${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4} >> vm_ips.txt" 47 | } 48 | } 49 | 50 | 51 | resource "openstack_networking_floatingip_v2" "fip_1" { 52 | pool = "public" 53 | } 54 | 55 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 56 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 57 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 58 | 59 | provisioner "file" { 60 | source = "test.txt" 61 | destination = "/tmp/test.txt" 62 | 63 | connection { 64 | type = "ssh" 65 | user = "cirros" 66 | password = "cubswin:)" 67 | host = "${openstack_networking_floatingip_v2.fip_1.address}" 68 | } 69 | } 70 | } 71 | 72 | 73 | -------------------------------------------------------------------------------- /provisioner/file_prov/test.txt: -------------------------------------------------------------------------------- 1 | This is the sample text file -------------------------------------------------------------------------------- /provisioner/file_prov/vars.tf: -------------------------------------------------------------------------------- 1 | # Below variables in vars.tf file 2 | 3 | provider "openstack" { 4 | user_name = "demo" 5 | tenant_name = "demo" 6 | password = "openstack123" 7 | auth_url = "http://10.0.1.4/identity" 8 | region = "RegionOne" 9 | domain_name = "default" 10 | } 11 | 12 | variable myimage { 13 | default = "2e0794ad-eb68-49a2-82b7-94a6b197a5ce" 14 | } 15 | 16 | variable mycimage { 17 | default = "a1f20383-ca57-4e6c-9c3d-a40d6246bbe6" 18 | } 19 | 20 | variable myflavor { 21 | default = "7" 22 | } 23 | 24 | variable mysg { 25 | default = "serversg1" 26 | } 27 | 28 | variable public_pool_id { 29 | default = "88c7bdb2-a1e4-4c0e-8263-c6b4eccb8072" 30 | } 31 | 32 | 33 | variable mykey { 34 | default = "mykey" 35 | } 36 | -------------------------------------------------------------------------------- /provisioner/local_exec/prov_ex1.tf: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Local provisioner exercise 5 | 6 | 7 | */ 8 | 9 | 10 | 11 | resource "openstack_networking_network_v2" "client_net" { 12 | name = "client_net" 13 | admin_state_up = "true" 14 | } 15 | 16 | resource "openstack_networking_subnet_v2" "client_subnet" { 17 | name = "client_subnet" 18 | network_id = "${openstack_networking_network_v2.client_net.id}" 19 | cidr = "10.10.10.0/24" 20 | } 21 | 22 | 23 | resource "openstack_networking_router_v2" "myrouter" { 24 | name = "myrouter" 25 | external_network_id = "${var.public_pool_id}" 26 | } 27 | 28 | resource "openstack_networking_router_interface_v2" "client_net_itf" { 29 | router_id = "${openstack_networking_router_v2.myrouter.id}" 30 | subnet_id = "${openstack_networking_subnet_v2.client_subnet.id}" 31 | } 32 | 33 | 34 | resource "openstack_compute_instance_v2" "vm1" { 35 | name = "vm1" 36 | image_id = "${var.myimage}" 37 | flavor_id = "${var.myflavor}" 38 | key_pair = "${var.mykey}" 39 | security_groups = ["${var.mysg}"] 40 | network { 41 | uuid = "${openstack_networking_network_v2.client_net.id}" 42 | } 43 | 44 | provisioner "local-exec" { 45 | command = "echo ${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4} >> vm_ips.txt" 46 | } 47 | } 48 | 49 | 50 | resource "openstack_networking_floatingip_v2" "fip_1" { 51 | pool = "public" 52 | } 53 | 54 | 55 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 56 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 57 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 58 | 59 | provisioner "local-exec" { 60 | command = "ping ${openstack_networking_floatingip_v2.fip_1.address} -c 25" 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /provisioner/local_exec/vars.tf: -------------------------------------------------------------------------------- 1 | # Below variables in vars.tf file 2 | 3 | provider "openstack" { 4 | user_name = "demo" 5 | tenant_name = "demo" 6 | password = "openstack123" 7 | auth_url = "http://10.0.1.4/identity" 8 | region = "RegionOne" 9 | domain_name = "default" 10 | } 11 | 12 | variable myimage { 13 | default = "2e0794ad-eb68-49a2-82b7-94a6b197a5ce" 14 | } 15 | 16 | variable mycimage { 17 | default = "a1f20383-ca57-4e6c-9c3d-a40d6246bbe6" 18 | } 19 | 20 | variable myflavor { 21 | default = "7" 22 | } 23 | 24 | variable mysg { 25 | default = "serversg1" 26 | } 27 | 28 | variable public_pool_id { 29 | default = "88c7bdb2-a1e4-4c0e-8263-c6b4eccb8072" 30 | } 31 | 32 | 33 | variable mykey { 34 | default = "mykey" 35 | } 36 | -------------------------------------------------------------------------------- /provisioner/null_resource/output.tf: -------------------------------------------------------------------------------- 1 | # output vm name variable 2 | 3 | output "vm-name" { 4 | value = "${openstack_compute_instance_v2.vm1.name}" 5 | } 6 | 7 | # output vm-id variable 8 | 9 | output "vm-id" { 10 | value = "${openstack_compute_instance_v2.vm1.id}" 11 | } 12 | 13 | # output vm-ip variable 14 | 15 | output "vm-ip" { 16 | value = "${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4}" 17 | } 18 | 19 | # output floating-ip variable 20 | 21 | output "vm-floating-ip" { 22 | value = "${openstack_networking_floatingip_v2.fip_1.address}" 23 | } -------------------------------------------------------------------------------- /provisioner/null_resource/stack.tf: -------------------------------------------------------------------------------- 1 | # Below resources in stack.tf file 2 | 3 | 4 | resource "openstack_networking_network_v2" "client_net" { 5 | name = "client_net" 6 | admin_state_up = "true" 7 | } 8 | 9 | resource "openstack_networking_subnet_v2" "client_subnet" { 10 | name = "client_subnet" 11 | network_id = "${openstack_networking_network_v2.client_net.id}" 12 | cidr = "172.1.1.0/24" 13 | } 14 | 15 | 16 | resource "openstack_networking_router_v2" "myrouter" { 17 | name = "myrouter" 18 | external_network_id = "${var.public_pool_id}" 19 | } 20 | 21 | resource "openstack_networking_router_interface_v2" "client_net_itf" { 22 | router_id = "${openstack_networking_router_v2.myrouter.id}" 23 | subnet_id = "${openstack_networking_subnet_v2.client_subnet.id}" 24 | } 25 | 26 | 27 | resource "openstack_compute_instance_v2" "vm1" { 28 | name = "myvm1" 29 | image_id = "${var.myimage}" 30 | flavor_id = "${var.myflavor}" 31 | key_pair = "${var.mykey}" 32 | security_groups = ["${var.mysg}"] 33 | network { 34 | uuid = "${openstack_networking_network_v2.client_net.id}" 35 | } 36 | } 37 | 38 | 39 | resource "openstack_networking_floatingip_v2" "fip_1" { 40 | pool = "public" 41 | } 42 | 43 | 44 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 45 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 46 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 47 | } 48 | 49 | 50 | 51 | 52 | /* 53 | The null_resource is a resource that allows you to configure provisioners that are not directly associated with a single existing resource. 54 | 55 | Basically we want to use provisioner(execute someaction) independently not part of any existing resource. 56 | 57 | Here we use Null resource to ping the floating ip (from local machine/provisioner) , the dependency of exeuction of Null rresource is completion of VM resource creation. 58 | */ 59 | 60 | resource "null_resource" "ping_floatingip" { 61 | 62 | depends_on = ["openstack_compute_instance_v2.vm1"] 63 | 64 | provisioner "local-exec" { 65 | command = "ping ${openstack_networking_floatingip_v2.fip_1.address} -c 10" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /provisioner/null_resource/vars.tf: -------------------------------------------------------------------------------- 1 | # Below variables in vars.tf file 2 | 3 | provider "openstack" { 4 | user_name = "demo" 5 | tenant_name = "demo" 6 | password = "openstack123" 7 | auth_url = "http://10.0.1.4/identity" 8 | region = "RegionOne" 9 | domain_name = "default" 10 | } 11 | 12 | variable myimage { 13 | default = "2e0794ad-eb68-49a2-82b7-94a6b197a5ce" 14 | } 15 | 16 | variable mycimage { 17 | default = "a1f20383-ca57-4e6c-9c3d-a40d6246bbe6" 18 | } 19 | 20 | variable myflavor { 21 | default = "7" 22 | } 23 | 24 | variable mysg { 25 | default = "serversg1" 26 | } 27 | 28 | variable public_pool_id { 29 | default = "88c7bdb2-a1e4-4c0e-8263-c6b4eccb8072" 30 | } 31 | 32 | 33 | variable mykey { 34 | default = "mykey" 35 | } 36 | -------------------------------------------------------------------------------- /provisioner/remote_exec/prov_ex2.tf: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ******Remote Provisioner exercise.***** 4 | 5 | 6 | How to run: 7 | terraform apply -parallelism=1 8 | */ 9 | 10 | 11 | 12 | resource "openstack_networking_network_v2" "client_net" { 13 | name = "client_net" 14 | admin_state_up = "true" 15 | } 16 | 17 | resource "openstack_networking_subnet_v2" "client_subnet" { 18 | name = "client_subnet" 19 | network_id = "${openstack_networking_network_v2.client_net.id}" 20 | cidr = "10.10.10.0/24" 21 | } 22 | 23 | 24 | resource "openstack_networking_router_v2" "myrouter" { 25 | name = "myrouter" 26 | external_network_id = "${var.public_pool_id}" 27 | } 28 | 29 | resource "openstack_networking_router_interface_v2" "client_net_itf" { 30 | router_id = "${openstack_networking_router_v2.myrouter.id}" 31 | subnet_id = "${openstack_networking_subnet_v2.client_subnet.id}" 32 | } 33 | 34 | 35 | resource "openstack_compute_instance_v2" "vm1" { 36 | name = "vm1" 37 | image_id = "${var.mycimage}" 38 | flavor_id = "${var.myflavor}" 39 | key_pair = "${var.mykey}" 40 | security_groups = ["${var.mysg}"] 41 | network { 42 | uuid = "${openstack_networking_network_v2.client_net.id}" 43 | } 44 | 45 | provisioner "local-exec" { 46 | command = "echo ${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4} >> vm_ips.txt" 47 | } 48 | } 49 | 50 | 51 | resource "openstack_networking_floatingip_v2" "fip_1" { 52 | pool = "public" 53 | } 54 | 55 | 56 | /* 57 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 58 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 59 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 60 | 61 | 62 | provisioner "remote-exec" { 63 | inline = [ 64 | "ifconfig", 65 | "ls -l", 66 | "ping -c 4 8.8.8.8" 67 | ] 68 | 69 | connection { 70 | type = "ssh" 71 | user = "cirros" 72 | password = "cubswin:)" 73 | host = "${openstack_networking_floatingip_v2.fip_1.address}" 74 | } 75 | } 76 | } 77 | */ 78 | 79 | 80 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 81 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 82 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 83 | 84 | provisioner "remote-exec" { 85 | script = "test.sh" 86 | 87 | connection { 88 | type = "ssh" 89 | user = "cirros" 90 | password = "cubswin:)" 91 | host = "${openstack_networking_floatingip_v2.fip_1.address}" 92 | } 93 | } 94 | } 95 | 96 | 97 | -------------------------------------------------------------------------------- /provisioner/remote_exec/test.sh: -------------------------------------------------------------------------------- 1 | ping -c 4 8.8.8.8 > /tmp/results.txt & 2 | -------------------------------------------------------------------------------- /provisioner/remote_exec/vars.tf: -------------------------------------------------------------------------------- 1 | # Below variables in vars.tf file 2 | 3 | provider "openstack" { 4 | user_name = "demo" 5 | tenant_name = "demo" 6 | password = "openstack123" 7 | auth_url = "http://10.0.1.4/identity" 8 | region = "RegionOne" 9 | domain_name = "default" 10 | } 11 | 12 | variable myimage { 13 | default = "2e0794ad-eb68-49a2-82b7-94a6b197a5ce" 14 | } 15 | 16 | variable mycimage { 17 | default = "a1f20383-ca57-4e6c-9c3d-a40d6246bbe6" 18 | } 19 | 20 | variable myflavor { 21 | default = "7" 22 | } 23 | 24 | variable mysg { 25 | default = "serversg1" 26 | } 27 | 28 | variable public_pool_id { 29 | default = "88c7bdb2-a1e4-4c0e-8263-c6b4eccb8072" 30 | } 31 | 32 | 33 | variable mykey { 34 | default = "mykey" 35 | } 36 | -------------------------------------------------------------------------------- /terraform_commands.md: -------------------------------------------------------------------------------- 1 | 2 | Providers & Plugin arch: 3 | ========================= 4 | 5 | A provider is responsible for understanding API interactions and exposing resources. 6 | 7 | Terraform supports approx 100+ providers (aws, opestack, azure, google cloud, kuberenetes etc). 8 | 9 | Early release(till 0.9), a single binary which includes all providers library. 10 | 11 | But 0.10 onwards, plugin architecture is introduced. providers are independent plugins. 12 | 13 | 14 | Terraform Commands: 15 | ===================== 16 | 17 | Below are the important commands, 18 | 19 | 1. terraform init 20 | 21 | 2. terraform plan 22 | 23 | 3. terraform apply 24 | 25 | 4. terraform show 26 | 27 | 5. terraform destroy 28 | 29 | 6. terraform output 30 | 31 | 32 | 33 | 34 | 35 | 1.terraform init - Initialization 36 | -------------------------------------------- 37 | 38 | Initialize a Terraform working directory, It Downloads the plugin required and initialize it. 39 | 40 | 41 | a. Create a directory 42 | 43 | ``` 44 | mkdir ex1 45 | ``` 46 | 47 | b. copy the ex1 terraform stack file (from the examples) to this directory 48 | 49 | ``` 50 | cp ex2a.tf ex1/. 51 | ``` 52 | 53 | c. Move in to the directory and perform terraform init. 54 | 55 | ``` 56 | cd ex1 57 | ls 58 | terraform init 59 | ``` 60 | you can see the output "provider plugin version, installation message etc." 61 | 62 | 63 | d. check the plugin details 64 | 65 | ``` 66 | ls -asl 67 | ``` 68 | you can see .terraform folder folder will be available, and inside the plugin file will be present. 69 | 70 | ``` 71 | $ls .terraform/plugins/linux_amd64/ 72 | lock.json terraform-provider-openstack_v1.3.0_x4 73 | ``` 74 | 75 | 76 | 2.terraform plan 77 | ------------------------------------- 78 | 79 | Generate and show an execution plan 80 | 81 | This command verifies the stack file is correct (no syntax issue) and able to communicate with provider. Error will be thrown, If any error in the file declaration, communication with provider. 82 | 83 | This is a preliminary step, before we apply our stack in the provider. 84 | 85 | 86 | ``` 87 | terraform plan 88 | ``` 89 | 90 | 91 | 3.terraform apply 92 | ------------------------------------- 93 | Builds the infrastructure 94 | 95 | This command apply our stack to the provider infrastructure . This file creates the state file(terraform.tfstate) in the same folder. 96 | 97 | ``` 98 | terraform apply 99 | ``` 100 | 101 | 102 | 4.terraform show 103 | ------------------------------------- 104 | Inspect Terraform state or plan 105 | 106 | This command displays your current state of the deployed stack. it reads the terraform state file and show the elements . 107 | 108 | ``` 109 | terraform show 110 | ``` 111 | 112 | 113 | 114 | 5.terraform destroy 115 | ------------------------------------- 116 | Destroy Terraform-managed infrastructure 117 | 118 | This command destroys your deployed stack. . 119 | 120 | ``` 121 | terraform destroy 122 | ``` 123 | 124 | 125 | 126 | *RULE: Please be sure, you run the terraform command in the directory where you have the terraform files.* 127 | 128 | 129 | 6.terraform output 130 | ------------------------------------- 131 | 132 | display the output variables 133 | 134 | 135 | Simple Demo 136 | ----------------- 137 | 138 | -------------------------------------------------------------------------------- /terraform_example_deployment.md: -------------------------------------------------------------------------------- 1 | Terraform : Openstack Infra: 2 | =============================== 3 | 4 | we will explain the complex infra deployment in openstack using Terraform. 5 | 6 | We use ubuntu 16.04 image and flavor 2 for this deployment. 7 | 8 | 9 | ![Infrastructure Diagram](deployment1/infra.png?raw=true) 10 | 11 | 12 | Terraform files: 13 | ---------------------- 14 | 15 | **vars.tf** 16 | 17 | **stack.tf** 18 | 19 | 20 | **cloudinit.yaml** 21 | 22 | **keys** 23 | 24 | 25 | Deployment: 26 | ----------- 27 | 28 | 1. create a directory and place the files. 29 | 30 | ``` 31 | mkdir infra1 32 | cd infra1 33 | cp /home/suresh/learn-terraform-with-openstack/deployment/* . 34 | ``` 35 | 36 | 2. Execute terraform init & plan 37 | 38 | ``` 39 | terraform init 40 | terraform plan 41 | ``` 42 | 43 | 3. Apply your infra 44 | 45 | ``` 46 | terraform apply 47 | ``` 48 | 49 | 4. verify your infra 50 | 51 | Check with openstack commands, or horizon dashboard 52 | 53 | 54 | 5. Check the terraform resources 55 | 56 | ``` 57 | terraform show 58 | ``` 59 | 60 | 61 | 62 | 63 | Testing: 64 | ----------- 65 | 66 | 1. SSH to the instances 67 | 2. web requests to the server -------------------------------------------------------------------------------- /terraform_exercises_part1.md: -------------------------------------------------------------------------------- 1 | Terraform Exercises: 2 | ===================== 3 | 4 | In this series of exercises, 5 | we are going to learn, How to write our openstack infrastructure in terraform configurations. 6 | 7 | Please download this repository to your machine. 8 | 9 | 10 | 11 | Exercises1: 12 | ===================== 13 | Objective: Demonstrate the openstack resource(vm) creation in terraform. we covers **provider,resource and output block** of terraform configuration in this exercise. 14 | 15 | Launch the openstack server instance with existing available resources (keypair, network, flavor, image, security group). 16 | 17 | 18 | Steps: 19 | ------------ 20 | 1. Create a new directory and create the ex1.tf file 21 | 22 | ``` 23 | mkdir ex1 24 | cd ex1 25 | vi ex1.tf 26 | ``` 27 | 28 | 2. create the provider blocks in the file 29 | 30 | https://www.terraform.io/docs/providers/openstack/index.html 31 | 32 | ``` 33 | provider "openstack" { 34 | user_name = "demo" 35 | tenant_name = "demo" 36 | password = "openstack123" 37 | auth_url = "http://10.0.1.6/identity" 38 | region = "RegionOne" 39 | domain_name = "default" 40 | } 41 | ``` 42 | 43 | 3. create the resource block in the file 44 | resource : instance (vm) 45 | 46 | ``` 47 | resource "openstack_compute_instance_v2" "vm1" { 48 | name = "vm1" 49 | image_id = "dea87f06-9fdc-410c-974f-470b057cfa2b" 50 | flavor_id = "1" 51 | key_pair = "mykey" 52 | security_groups = ["default"] 53 | network { 54 | uuid = "db4a268a-465d-40d7-9db2-54b82d945bec" 55 | } 56 | } 57 | ``` 58 | 59 | 4. Execute terraform init & plan 60 | 61 | ``` 62 | terraform init 63 | terraform plan 64 | ``` 65 | 66 | 67 | 5. Apply your infra 68 | 69 | ``` 70 | terraform apply 71 | ``` 72 | 73 | 6. verify your infra 74 | 75 | Check with openstack commands, or horizon dashboard 76 | 77 | 78 | 7. Check the terraform resource properties 79 | 80 | ``` 81 | terraform show 82 | ``` 83 | 84 | 85 | 8. Create the output variable to display the VM attributes. 86 | 87 | ``` 88 | output "vm-name" { 89 | value = "${openstack_compute_instance_v2.vm1.name}" 90 | } 91 | 92 | output "vm-id" { 93 | value = "${openstack_compute_instance_v2.vm1.id}" 94 | } 95 | 96 | output "vm-ip" { 97 | value = "${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4}" 98 | } 99 | 100 | ``` 101 | 102 | 9. perform terraform plan and apply, to check the output. 103 | 104 | 105 | 10. destroy your infra 106 | 107 | ``` 108 | terraform destroy 109 | ``` 110 | 111 | 112 | 11. Use environment(rc file) variable instead of provider block and repeat this exercise. 113 | 114 | 115 | ``` 116 | export OS_USERNAME=demo 117 | export OS_PASSWORD=openstack123 118 | export OS_REGION_NAME=RegionOne 119 | export OS_TENANT_NAME=demo 120 | export OS_USER_DOMAIN_ID=default 121 | export OS_AUTH_URL=http://10.0.1.6/identity 122 | ``` 123 | 124 | 125 | 126 | Referneces: 127 | =============== 128 | 1. https://www.terraform.io/docs/providers/openstack/index.html 129 | 2. https://www.terraform.io/docs/providers/openstack/r/compute_instance_v2.html 130 | -------------------------------------------------------------------------------- /terraform_exercises_part2.md: -------------------------------------------------------------------------------- 1 | Exercises2: 2 | ===================== 3 | 4 | Objective: Demonstrate the openstack resource creation(vm, floatingip, floating ip association) in terraform. 5 | 6 | we covers **resource, variable, output block** of terraform configuration in this exercise. 7 | 8 | 9 | Steps: 10 | ------------ 11 | 12 | 1) In the Exercise1, 13 | Use variable block to declare the image, flavor, key, security group, network. 14 | 15 | ``` 16 | variable myimage { 17 | default = "dea87f06-9fdc-410c-974f-470b057cfa2b" 18 | } 19 | ``` 20 | 21 | 2) Terraform plan and apply 22 | 23 | 3) Add floating IP resource. 24 | 25 | ``` 26 | resource "openstack_networking_floatingip_v2" "fip_1" { 27 | pool = "public" 28 | } 29 | ``` 30 | 4) Terraform Plan,apply and show 31 | 32 | 5) Add floating IP association 33 | 34 | 35 | ``` 36 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 37 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 38 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 39 | } 40 | 41 | ``` 42 | 43 | 6) Terraform plan , apply and show. 44 | 45 | 46 | 47 | Referneces: 48 | =============== 49 | 1. https://www.terraform.io/docs/providers/openstack/index.html -------------------------------------------------------------------------------- /terraform_exercises_part3.md: -------------------------------------------------------------------------------- 1 | Terraform Exercises - Part3: 2 | ============================ 3 | Exercise3: 4 | ============================ 5 | 6 | In this exercise, we build our infra as below, 7 | 8 | ![Infrastructure Diagram](exercises/ex3.png?raw=true) 9 | 10 | The following resources will be created. 11 | 12 | 1) Keypair 13 | 14 | 2) Security Groups and Rules 15 | 16 | 3) Network and Subnet 17 | 18 | 4) Router 19 | 20 | 5) Floating IP 21 | 22 | 6) Instance 23 | 24 | we will use the Ubuntu Image and flavor. 25 | 26 | 27 | we will use multiple terraform files to build our infra. 28 | 29 | variables will be stored in vars.tf file. 30 | 31 | resources will be in stack.tf file. 32 | 33 | output stuff will be in output.tf file 34 | 35 | 36 | 37 | vars.tf 38 | --------- 39 | 40 | 1. create a vars.tf file and update the image, flavor, and public pool id. 41 | 42 | 43 | stack.tf 44 | ---------- 45 | 46 | 47 | **keypair:** 48 | 49 | 50 | ``` 51 | resource "openstack_compute_keypair_v2" "mykey1" { 52 | name = "mykey1" 53 | public_key = "${file("mykey.pub")}" 54 | } 55 | 56 | ``` 57 | 58 | Note: mykey.pub , mykey (private key) file present in exercise folder. Please copy this file in to the folder. 59 | 60 | 61 | **Security Groups and Rules** 62 | 63 | ``` 64 | resource "openstack_networking_secgroup_v2" "my_secgroup" { 65 | name = "my_secgroup" 66 | description = "Allow all" 67 | } 68 | 69 | resource "openstack_networking_secgroup_rule_v2" "rule1" { 70 | direction = "ingress" 71 | ethertype = "IPv4" 72 | security_group_id = "${openstack_networking_secgroup_v2.my_secgroup.id}" 73 | } 74 | ``` 75 | 76 | **Network and Subnet** 77 | 78 | ``` 79 | resource "openstack_networking_network_v2" "client_net" { 80 | name = "client_net" 81 | admin_state_up = "true" 82 | } 83 | 84 | resource "openstack_networking_subnet_v2" "client_subnet" { 85 | name = "client_subnet" 86 | network_id = "${openstack_networking_network_v2.client_net.id}" 87 | cidr = "172.1.1.0/24" 88 | } 89 | 90 | ``` 91 | 92 | **Router** 93 | 94 | ``` 95 | resource "openstack_networking_router_v2" "myrouter" { 96 | name = "myrouter" 97 | external_gateway = "${var.public_pool_id}" 98 | } 99 | 100 | resource "openstack_networking_router_interface_v2" "client_net_itf" { 101 | router_id = "${openstack_networking_router_v2.myrouter.id}" 102 | subnet_id = "${openstack_networking_subnet_v2.client_subnet.id}" 103 | } 104 | 105 | ``` 106 | 107 | **Floating IP** 108 | 109 | 110 | ``` 111 | resource "openstack_networking_floatingip_v2" "fip_1" { 112 | pool = "public" 113 | } 114 | 115 | 116 | resource "openstack_compute_floatingip_associate_v2" "fip_1" { 117 | floating_ip = "${openstack_networking_floatingip_v2.fip_1.address}" 118 | instance_id = "${openstack_compute_instance_v2.vm1.id}" 119 | } 120 | 121 | ``` 122 | 123 | **Instance** 124 | ``` 125 | resource "openstack_compute_instance_v2" "vm1" { 126 | name = "vm1" 127 | image_id = "${var.myimage}" 128 | flavor_id = "${var.myflavor}" 129 | key_pair = "${openstack_compute_keypair_v2.mykey1.name}" 130 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 131 | network { 132 | uuid = "${openstack_networking_network_v2.client_net.id}" 133 | } 134 | } 135 | 136 | ``` 137 | 138 | 139 | output.tf 140 | ---------- 141 | 142 | ``` 143 | 144 | # output vm name variable 145 | 146 | output "vm-name" { 147 | value = "${openstack_compute_instance_v2.vm1.name}" 148 | } 149 | 150 | # output vm-id variable 151 | 152 | output "vm-id" { 153 | value = "${openstack_compute_instance_v2.vm1.id}" 154 | } 155 | 156 | # output vm-ip variable 157 | 158 | output "vm-ip" { 159 | value = "${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4}" 160 | } 161 | 162 | # output floating-ip variable 163 | 164 | output "vm-floating-ip" { 165 | value = "${openstack_networking_floatingip_v2.fip_1.address}" 166 | } 167 | 168 | 169 | ``` 170 | 171 | 172 | Execution 173 | ------------ 174 | ``` 175 | terraform init 176 | terraform plan 177 | terraform apply 178 | terraform destroy 179 | ``` 180 | 181 | 182 | 183 | References: 184 | =============== 185 | 186 | 1. https://www.terraform.io/docs/providers/openstack/index.html 187 | 188 | -------------------------------------------------------------------------------- /terraform_exercises_part4.md: -------------------------------------------------------------------------------- 1 | Terraform Exercises - Part4: 2 | ============================ 3 | 4 | Exercise4: 5 | ----------- 6 | 7 | In this exercise, we will use **data resource** block to define our cloudinit file (cloud-config, scripts) 8 | 9 | we will use exercise3 stack, and update the cloudinit scripts. 10 | 11 | 12 | Define the cloudinit resource as below, 13 | 14 | ``` 15 | data "template_cloudinit_config" "init_script" { 16 | part { 17 | content_type = "text/cloud-config" 18 | content = "${file("cloudinit.yaml")}" 19 | } 20 | } 21 | 22 | ``` 23 | 24 | Use the cloudinit resource in instance resource. 25 | 26 | ``` 27 | resource "openstack_compute_instance_v2" "vm1" { 28 | name = "vm1" 29 | image_id = "${var.myimage}" 30 | flavor_id = "${var.myflavor}" 31 | key_pair = "${openstack_compute_keypair_v2.mykey1.name}" 32 | security_groups = ["${openstack_networking_secgroup_v2.my_secgroup.id}"] 33 | network { 34 | uuid = "${openstack_networking_network_v2.client_net.id}" 35 | } 36 | user_data = "${data.template_cloudinit_config.init_script.rendered}" 37 | } 38 | 39 | ``` 40 | 41 | 42 | 43 | Other Methods 44 | -------------- 45 | 46 | we can directly specify the shell commands in the user_data as below, 47 | 48 | 49 | ``` 50 | user_data = "#!/bin/bash\n\nscreen -d -m ping 8.8.8.8" 51 | 52 | ``` 53 | 54 | 55 | References: 56 | =============== 57 | 58 | 1. http://cloudinit.readthedocs.io/en/latest/topics/examples.html 59 | 60 | 2. https://www.terraform.io/docs/providers/template/d/cloudinit_config.html# 61 | 62 | -------------------------------------------------------------------------------- /terraform_how_to_write.md: -------------------------------------------------------------------------------- 1 | Terraform configurations: 2 | ============================ 3 | Terraform uses text files to describe infrastructure and to set variables. These text files are called Terraform configurations and end in .tf. 4 | 5 | Two formats are supported. 6 | 7 | **1. JSON** 8 | 9 | **2. Terraform format (More human readable, support comments) - Preferred.** 10 | 11 | Terraform format ends in .tf and JSON format ends in .tf.json 12 | 13 | Load all the files (.tf or .tf.json) present in the directory. 14 | 15 | 16 | Configuration Syntax: 17 | ============================ 18 | 19 | Terraform syntax is called HashiCorp Configuration Language (HCL). 20 | 21 | 1.provider block 22 | --------------------- 23 | 24 | This block contains Providers configuration such as auth details, endpoint URLs, etc. 25 | 26 | 27 | ``` 28 | provider "openstack" { 29 | user_name = "demo" 30 | tenant_name = "demo" 31 | password = "openstack123" 32 | auth_url = "http://10.0.1.6/identity" 33 | region = "RegionOne" 34 | domain_name = "default" 35 | } 36 | 37 | ``` 38 | 39 | 2.Variable 40 | --------------------- 41 | 42 | ``` 43 | variable image_id { 44 | type = "string" 45 | default = "dea87f06-9fdc-410c-974f-470b057cfa2b" 46 | } 47 | ``` 48 | 49 | This variable can be referred as "${var.image_id}". 50 | 51 | 52 | 53 | 3.Resource 54 | --------------------- 55 | 56 | Resources are a component of your infrastructure. It might be some low level /high level component. Example: In openstack terminology networks, security groups, instance, key-pair etc. 57 | 58 | The resource block creates a resource of the given TYPE (first parameter) and NAME (second parameter). The combination of the type and name must be unique. 59 | 60 | ``` 61 | resource "openstack_compute_instance_v2" "vm1" { 62 | image_id = "${var.image_id}" 63 | } 64 | 65 | ``` 66 | 67 | 4.Output variable 68 | --------------------- 69 | 70 | Outputs define values that will be highlighted to the user when Terraform applies. 71 | 72 | Example: Fixed IP and FloatingIP of the VM. 73 | 74 | 75 | ``` 76 | # output vm-ip variable 77 | output "vm-ip" { 78 | value = "${openstack_compute_instance_v2.vm1.network.0.fixed_ip_v4}" 79 | } 80 | ``` 81 | 82 | 5.data sources 83 | --------------------- 84 | 85 | Data sources allow data to be fetched or computed for use elsewhere in Terraform configuration. 86 | 87 | Example: Read the file contents 88 | 89 | Providers are responsible in Terraform for defining and implementing data sources 90 | 91 | ``` 92 | data "template_file" "cloudscript" { 93 | template = "${file("cloudinit.yaml")}" 94 | } 95 | 96 | ``` 97 | 98 | 99 | References: 100 | --------------- 101 | 102 | 1. https://www.terraform.io/docs/configuration/index.html 103 | 104 | 2. https://www.terraform.io/docs/providers/openstack/index.html 105 | -------------------------------------------------------------------------------- /terraform_installation.md: -------------------------------------------------------------------------------- 1 | How to Install Terraform: 2 | ========================= 3 | 4 | I am using **Ubuntu 16.04.04 LTS** for this demonstration. 5 | 6 | 7 | The terraform latest version is **Terraform 0.11.5** 8 | 9 | 10 | 1)Download the Terraform from the below link 11 | ---------------------------------------------- 12 | 13 | https://www.terraform.io/downloads.html 14 | 15 | 16 | ``` 17 | wget https://releases.hashicorp.com/terraform/0.11.5/terraform_0.11.5_linux_amd64.zip 18 | ``` 19 | 20 | 21 | 2)unzip it 22 | ----------------------- 23 | 24 | ``` 25 | unzip terraform_0.11.5_linux_amd64.zip 26 | ``` 27 | 28 | 3)Move the terraform binary in to bin path. 29 | ---------------------------------------------- 30 | 31 | ``` 32 | sudo mv terraform /usr/bin/. 33 | ``` 34 | 35 | Thats all 36 | 37 | 38 | 4)Verification 39 | ----------------------- 40 | 41 | ``` 42 | terraform version 43 | ``` 44 | 45 | 46 | References: 47 | ------------- 48 | 49 | 1. https://www.terraform.io/downloads.html 50 | 51 | 2. https://www.terraform.io/intro/getting-started/install.html 52 | -------------------------------------------------------------------------------- /terraform_introduction.md: -------------------------------------------------------------------------------- 1 | 2 | 1.Infrastructure as Code 3 | ========================= 4 | 5 | Infrastructure as code is the process of managing and provisioning computer data centers through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools. 6 | 7 | https://en.wikipedia.org/wiki/Infrastructure_as_Code 8 | 9 | 10 | 2.What is Terraform? 11 | ===================== 12 | 13 | Terraform is used to create, manage, and update infrastructure resources such as physical machines, VMs, network switches, containers, and more. Almost any infrastructure type can be represented as a resource in Terraform. 14 | 15 | In Simple, 16 | 17 | Terraform is a tool for 18 | 19 | i) building, 20 | 21 | ii) changing, 22 | 23 | iii) versioning 24 | 25 | your infrastructure. 26 | 27 | 28 | 29 | 3.Use Cases : 30 | ===================== 31 | 32 | 1. Deploying and Maintaining Multi-Tier Applications Infrastructure (DB, WEB, LOG, Load balancer, etc) 33 | 34 | 2. Software Demos 35 | 36 | 3. Disposable Environments 37 | 38 | 4. Multi cloud Support (cloud agnostic) 39 | 40 | 41 | 4.Providers 42 | ============ 43 | 44 | Terraform can manage existing and popular service providers such as, 45 | 46 | 1) openstack 47 | 48 | 2) aws 49 | 50 | 3) google cloud 51 | 52 | 4) azure 53 | 54 | 5) kubernetes 55 | 56 | 6) DigitalOcean 57 | 58 | 7) .......etc...... 59 | 60 | 61 | https://www.terraform.io/docs/providers/index.html 62 | 63 | 64 | 65 | 5.Key Features 66 | ============== 67 | 68 | 69 | Infrastructure as Code 70 | ------------------------ 71 | 72 | a. Infrastructure is described using a high-level configuration syntax. 73 | 74 | b. This allows versioning 75 | 76 | c. infrastructure can be shared and re-used. 77 | 78 | 79 | 80 | Execution Plans 81 | ------------------------ 82 | Terraform planning step will evaluate and generates the execution plan. This shows what will be output ,when you apply this stack. 83 | 84 | 85 | 86 | Paraller creation (Resource graph) 87 | ----------------------------------- 88 | 89 | Parallelizes the creation and modification of any non-dependent resources 90 | 91 | 92 | Change Automation 93 | ------------------ 94 | 95 | Complex changesets can be applied to your infrastructure with minimal human interaction 96 | 97 | Incremental changes of your existing infrastructure can be updated. 98 | 99 | 100 | 101 | 102 | 103 | 6.Configuration File 104 | ===================== 105 | 106 | Configuration files describe to Terraform the components needed to run a single application or your entire datacenter. 107 | 108 | As the configuration changes, Terraform is able to determine what changed and create incremental execution plans which can be applied. 109 | 110 | 111 | 112 | 113 | 7.References: 114 | ============== 115 | 116 | https://en.wikipedia.org/wiki/Infrastructure_as_Code 117 | 118 | https://www.terraform.io/ 119 | 120 | 121 | https://www.terraform.io/intro/use-cases.html 122 | 123 | 124 | -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | Resource dependency 2 | resource graph 3 | 4 | 5 | https://www.terraform.io/docs/configuration/resources.html#count 6 | https://www.terraform.io/docs/internals/graph.html 7 | https://www.terraform.io/docs/commands/graph.html 8 | --------------------------------------------------------------------------------