Repository: Terraform-VMWare-Modules/terraform-vsphere-vm
Branch: master
Commit: e47cf7eb9006
Files: 28
Total size: 61.6 KB
Directory structure:
gitextract_pni6tlpg/
├── .github/
│ └── stale.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── examples/
│ ├── README.md
│ ├── example-Windows-data_disk.tf
│ ├── example-linux-Network.tf
│ ├── example-linux-depend_on.tf
│ └── example-vmname.tf
├── main.tf
├── output.tf
├── tests/
│ ├── sanity/
│ │ ├── .terraform.lock.hcl
│ │ ├── README.md
│ │ ├── apply.sh
│ │ ├── cleanup.sh
│ │ ├── connection.tf
│ │ ├── main.tf
│ │ └── plan.sh
│ └── smoke/
│ ├── .terraform.lock.hcl
│ ├── README.md
│ ├── apply.sh
│ ├── connection.tf
│ ├── main.tf
│ └── plan.sh
├── variables.tf
└── versions.tf
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/stale.yml
================================================
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- enhancement
- pinned
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: enable
================================================
FILE: .gitignore
================================================
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# .tfvars files
*.tfvars
#Sensetive Info
*private*
#VIM Junk
*.un~
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at arman@rmaan.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to terraform-vsphere-vm
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
- Reporting a bug
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer
## We Do have a Dedicated Slack Channel
You can join the channel using the following [link](https://join.slack.com/t/terraformvmware/shared_invite/zt-elw5yhds-kPT_QMBWaHGLCPkPJKxYeA).
## We Develop with Github
We use github to host code, to track issues and feature requests, as well as accept pull requests.
## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests
Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests:
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests.
1. This should be done via sanity test section.
2. Attach copy of the passed TF Plan. (Remove sensitive info if necessary)
3. If you've changed variables/functionality, update the documentation.
4. Ensure the test suite passes.
5. Make sure your code lints.
6. Issue that pull request!
## Any contributions you make will be under the MIT Software License
In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
## Report bugs using Github's [issues](https://github.com/Terraform-VMWare-Modules/terraform-vsphere-vm/issues)
We use GitHub issues to track public bugs. Report a bug by [opening a new issue](); it's that easy!
## Write bug reports with detail, background, and sample code
**Great Bug Reports** tend to have:
- A quick summary and/or background
- Steps to reproduce
- Be specific!
- Give sample code if you can.
- What you expected would happen
- What actually happens
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
People *love* thorough bug reports. I'm not even kidding.
## License
By contributing, you agree that your contributions will be licensed under its MIT License.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
================================================
FILE: README.md
================================================
# Terraform vSphere Module
 [](https://registry.terraform.io/modules/Terraform-VMWare-Modules/vm/vsphere/) [](https://github.com/Terraform-VMWare-Modules/terraform-vsphere-vm/releases) [](LICENSE)
For Virtual Machine Provisioning with (Linux/Windows) customization. Based on Terraform v0.13 and up, this module includes most of the advanced features available in resource `vsphere_virtual_machine`.
## Deploys (Single/Multiple) Virtual Machines to your vSphere environment
This Terraform module deploys single or multiple virtual machines of type (Linux/Windows) with the following features:
- Ability to specify Linux or Windows VM customization.
- Ability to add multiple network cards for the VM
- Ability to assign tags and custom variables.
- Ability to configure advanced features for a VM.
- Ability to deploy either a datastore or a datastore cluster.
- Add extra data disk (up to 15) to the VM.
- Different datastores for data disks (datastore_id).
- Different storage policies for data disks (storage_policy_id).
- Different scsi_controllers per disk, including data disks.
- Ability to define depend on using variable vm_depends_on & tag_depends_on
> Note: For the module to work, it needs several required variables corresponding to existing resources in vSphere. Please refer to the variable section for the list of required variables.
## Getting started
The following example contains the bare minimum options to be configured for (Linux/Windows) VM deployment. You can choose between Windows and Linux customization by simply using the `is_windows_image` boolean switch.
You can also download the entire module and use your predefined variables to map your entire vSphere environment and use it within this module.
First, create a `main.tf` file.
Next, copy the code below and fill in the required variables.
```hcl
# Configure the VMware vSphere Provider
provider "vsphere" {
user = "fill"
password = "fill"
vsphere_server = "fill"
# if you have a self-signed cert
allow_unverified_ssl = true
}
# Deploy 2 linux VMs
module "example-server-linuxvm" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "X.X.X"
vmtemp = "VM Template Name (Should Alrerady exist)"
instances = 2
vmname = "example-server-linux"
vmrp = "esxi/Resources - or name of a resource pool"
network = {
"Name of the Port Group in vSphere" = ["10.13.113.2", "10.13.113.3"] # To use DHCP create Empty list ["",""]; You can also use a CIDR annotation;
}
vmgateway = "10.13.113.1"
dc = "Datacenter"
datastore = "Data Store name(use datastore_cluster for datastore cluster)"
}
```
Finally, run
```bash
terraform run
```
## Advanced Usage
The module includes several option switches, which you can use to enable various VM provisioning features.
- You can use `is_windows_image = true` to set the customization type to Windows (By default, it is Linux customization)
- You can use `windomain = "somedomain.com"` to join a Windows server to an AD domain.
- Requires following additional variables
- `domainuser` - Domain account with necessary privileges to join a computer to the domain.
- `domainpass` - Domain user password.
- `is_windows_image` needs to be set to `true` to force the module to use Windows customization.
> Note: When deploying a windows server in WorkGroup, we recommend keeping the Local Admin password set to its default and change it later via a script. Unfortunately, Terraform will re-deploy the entire server if you change the local admin password.
Below is an example of windows deployment with some of the available feature sets. For a complete list of available features, please refer to [variable.tf](https://github.com/Terraform-VMWare-Modules/terraform-vsphere-vm/blob/master/variables.tf)
```hcl
module "example-server-windowsvm-advanced" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "X.X.X"
dc = "Datacenter"
vmrp = "cluster/Resources" #Works with ESXi/Resources
vmfolder = "Cattle"
datastore_cluster = "Datastore Cluster" #You can use datastore variable instead
vmtemp = "TemplateName"
instances = 2
vmname = "AdvancedVM"
vmnameformat = "%03d" #To use three decimal with leading zero vmnames will be AdvancedVM001,AdvancedVM002
domain = "somedomain.com"
network = {
"Name of the Port Group in vSphere" = ["10.13.113.2", "10.13.113.3"] # To use DHCP create Empty list ["",""]; You can also use a CIDR annotation;
"Second Network Card" = ["", ""]
}
ipv4submask = ["24", "8"]
network_type = ["vmxnet3", "vmxnet3"]
tags = {
"terraform-test-category" = "terraform-test-tag"
}
data_disk = {
disk1 = {
size_gb = 30,
thin_provisioned = false,
data_disk_scsi_controller = 0,
},
disk2 = {
size_gb = 70,
thin_provisioned = true,
data_disk_scsi_controller = 1,
datastore_id = "datastore-90679"
}
}
scsi_bus_sharing = "physicalSharing" // The modes are physicalSharing, virtualSharing, and noSharing
scsi_type = "lsilogic" // Other acceptable value "pvscsi"
scsi_controller = 0 // This will assign OS disk to controller 0
dns_server_list = ["192.168.0.2", "192.168.0.1"]
enable_disk_uuid = true
vmgateway = "192.168.0.1"
auto_logon = true
run_once = ["command01", "command02"] // You can also run Powershell commands
orgname = "Terraform-Module"
workgroup = "Module-Test"
is_windows_image = true
firmware = "efi"
local_adminpass = "Password@Strong"
}
output "vmnames" {
value = module.example-server-windowsvm-advanced.VM
}
output "vmnameswip" {
value = module.example-server-windowsvm-advanced.ip
}
```
## Contributing
This module is the work of many contributors. We appreciate your help!
To contribute, please read the [contribution guidelines](https://github.com/Terraform-VMWare-Modules/terraform-vsphere-vm/blob/master/CONTRIBUTING.md)
## License
[MIT](LICENSE)
================================================
FILE: examples/README.md
================================================
# Terraform vSphere examples
This directory contains various examples for deplpyong Linux/Windows VMs to a vSphere vCenter.
## Getting started
__Create a connection.tf file and copy the following code.__
```hcl
# Configure the VMware vSphere Provider
provider "vsphere" {
user = "fill"
password = "fill"
vsphere_server = "fill"
# if you have a self-signed cert
allow_unverified_ssl = true
}
```
__Copy any of the exmpale tf files and fill the required data then run terraform init/plan/apply.__
================================================
FILE: examples/example-Windows-data_disk.tf
================================================
data "vsphere_storage_policy" "policy" {
name = "policy1"
}
module "example-server-windowsvm-advanced" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "X.X.X"
dc = "Datacenter"
vmrp = "cluster/Resources" #Works with ESXi/Resources
vmfolder = "Cattle"
datastore_cluster = "Datastore Cluster" #You can use datastore variable instead
vmtemp = "TemplateName"
instances = 2
vmname = "AdvancedVM"
domain = "somedomain.com"
network = {
"Name of the Port Group in vSphere" = ["10.13.113.2", "10.13.113.3"] # To use DHCP create Empty list ["",""]
}
template_storage_policy_id = [data.vsphere_storage_policy.this.id] #Policy ID for the template disks
data_disk = {
disk1 = {
size_gb = 30,
thin_provisioned = false,
data_disk_scsi_controller = 0,
storage_policy_id = "ff45cc66-b624-4621-967f-1aef6437f568" #Different policy ID for data disks
},
disk2 = {
size_gb = 70,
thin_provisioned = true,
data_disk_scsi_controller = 1,
datastore_id = "datastore-90679"
}
}
scsi_bus_sharing = "physicalSharing" // The modes are physicalSharing, virtualSharing, and noSharing
scsi_type = "lsilogic" // Other acceptable value "pvscsi"
scsi_controller = 0 // This will assign OS disk to controller 0
dns_server_list = ["192.168.0.2", "192.168.0.1"]
vmgateway = "192.168.0.1"
enable_disk_uuid = true
orgname = "Terraform-Module"
workgroup = "Module-Test"
is_windows_image = true
firmware = "efi"
local_adminpass = "Password@Strong"
}
================================================
FILE: examples/example-linux-Network.tf
================================================
// Example of Linux VM with more Advanced Features
module "example-server-linuxvm-advanced" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "Latest X.X.X"
dc = "Datacenter"
vmrp = "cluster/Resources"
vmfolder = "Cattle"
datastore_cluster = "Datastore Cluster"
vmtemp = "TemplateName"
instances = 2
vmname = "AdvancedVM"
domain = "somedomain.com"
ipv4submask = ["24", "8"]
network = {
"Network01" = ["10.13.113.2", "10.13.113.3"] # To use DHCP create Empty list ["",""]
"Network02" = ["", ""] #Second Network will use the DHCP
}
disk_datastore = "vsanDatastore"
dns_server_list = ["192.168.0.2", "192.168.0.1"]
vmgateway = "192.168.0.1"
network_type = ["vmxnet3", "vmxnet3"]
}
// Example of Linux VM with Network CIDR
module "example-server-linuxvm-advanced" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "Latest X.X.X"
dc = "Datacenter"
vmrp = "cluster/Resources"
vmfolder = "Cattle"
datastore_cluster = "Datastore Cluster"
vmtemp = "TemplateName"
instances = 2
vmname = "AdvancedVM"
domain = "somedomain.com"
network = {
"Network01" = ["10.13.113.2/28", "10.13.113.3/28"] # To use DHCP create Empty list ["",""]
"Network02" = ["", ""] #Second Network will use the DHCP
"Network03" = ["10.13.0.2/26", "10.13.0.3/26"]
}
disk_datastore = "vsanDatastore"
dns_server_list = ["192.168.0.2", "192.168.0.1"]
vmgateway = "192.168.0.1"
network_type = ["vmxnet3", "vmxnet3"]
}
================================================
FILE: examples/example-linux-depend_on.tf
================================================
// Simple Linux VM deployment
module "example-server-linuxvm" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "Latest X.X.X"
vmtemp = "TemplateName"
instances = 1
vmname = "example-server-windows"
vmrp = "esxi/Resources"
network = {
"Network01" = ["10.13.113.2", "10.13.113.3"] # To use DHCP create Empty list ["",""]
"Network02" = ["", ""] #Second Network will use the DHCP
}
dc = "Datacenter"
datastore = "Data Store name(use datastore_cluster for datastore cluster)"
}
// Example of Linux VM with more Advanced Features
module "example-server-linuxvm-advanced" {
source = "Terraform-VMWare-Modules/vm/vsphere"
vm_depends_on = [module.example-server-linuxvm] # This force the second module to wait for first VM to be created first
version = "Latest X.X.X"
dc = "Datacenter"
vmrp = "cluster/Resources"
vmfolder = "Cattle"
datastore_cluster = "Datastore Cluster"
vmtemp = "TemplateName"
instances = 2
cpu_number = 2
ram_size = 2096
cpu_hot_add_enabled = true
cpu_hot_remove_enabled = true
memory_hot_add_enabled = true
vmname = "AdvancedVM"
domain = "somedomain.com"
ipv4submask = ["24", "8"]
network = {
"Network01" = ["10.13.113.2", "10.13.113.3"] # To use DHCP create Empty list ["",""]
"Network02" = ["", ""] #Second Network will use the DHCP
}
dns_server_list = ["192.168.0.2", "192.168.0.1"]
vmgateway = "192.168.0.1"
network_type = ["vmxnet3", "vmxnet3"]
tags = {
"terraform-test-category" = "terraform-test-tag"
"terraform-test-category-02" = "terraform-test-tag-02"
}
}
================================================
FILE: examples/example-vmname.tf
================================================
// Single VM deployment with literal name
module "example-server-single" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "Latest X.X.X"
vmtemp = "TemplateName"
staticvmname = "liternalvmname"
vmrp = "esxi/Resources"
network = {
"Name of the Port Group in vSphere" = ["10.13.113.2"]
}
dc = "Datacenter"
datastore = "Data Store name(use datastore_cluster for datastore cluster)"
}
# Vmname Output -> liternalvmname
//Sclae out Static VMs
variable "name" {
default = ["staticvmname", "staticvmname01"]
}
module "example-server-single" {
source = "Terraform-VMWare-Modules/vm/vsphere"
for_each = toset(var.name)
version = "Latest X.X.X"
vmtemp = "TemplateName"
staticvmname = "liternalvmname"
vmrp = "esxi/Resources"
network = {
"Name of the Port Group in vSphere" = ["10.13.113.2"]
}
dc = "Datacenter"
datastore = "Data Store name(use datastore_cluster for datastore cluster)"
}
// Example of multiple VM deployment with complex naming standard
# Define Environment Variable to switch between Environments
variable "env" {
default = "dev"
}
module "example-server-multi" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "Latest X.X.X"
vmtemp = "TemplateName"
instances = 2
vmname = "advancevm"
vmnameformat = "%03d${var.env}"
vmrp = "esxi/Resources"
network = {
"Name of the Port Group in vSphere" = ["10.13.113.2", ""]
}
dc = "Datacenter"
datastore = "Data Store name(use datastore_cluster for datastore cluster)"
}
# Vmname Output -> advancevm001dev, advancevm002dev
#
//Example of appending domain name to vm name
module "example-server-fqdnvmname" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "Latest X.X.X"
vmtemp = "TemplateName"
instances = 2
vmname = "advancevm"
vmnameformat = "%03d"
domain = "somedomain.com"
fqdnvmname = true
vmrp = "esxi/Resources"
network = {
"Name of the Port Group in vSphere" = ["10.13.113.2", ""]
}
dc = "Datacenter"
datastore = "Data Store name(use datastore_cluster for datastore cluster)"
}
# Vmname Output -> advancevm001.somedomain.com, advancevm002.somedomain.com
#
//Example of using a starting number other than "1" for the vmname with multiple instances
module "example-server-vmstartcount" {
source = "Terraform-VMWare-Modules/vm/vsphere"
version = "Latest X.X.X"
vmtemp = "TemplateName"
instances = 2
vmstartcount = 5
vmname = "advancevm"
vmnameformat = "%03d"
vmrp = "esxi/Resources"
network = {
"Name of the Port Group in vSphere" = ["10.13.113.2", ""]
}
dc = "Datacenter"
datastore = "Data Store name(use datastore_cluster for datastore cluster)"
}
# Vmname Output -> advancevm005, advancevm006
================================================
FILE: main.tf
================================================
data "vsphere_datacenter" "dc" {
name = var.dc
}
data "vsphere_datastore_cluster" "datastore_cluster" {
count = var.datastore_cluster != "" ? 1 : 0
name = var.datastore_cluster
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_datastore" "datastore" {
count = var.datastore != "" && var.datastore_cluster == "" ? 1 : 0
name = var.datastore
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_datastore" "disk_datastore" {
count = var.disk_datastore != "" ? 1 : 0
name = var.disk_datastore
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_resource_pool" "pool" {
count = var.vmrp != "" ? 1 : 0
name = var.vmrp
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_network" "network" {
count = length(var.network)
name = var.network_delimiter != null ? split(var.network_delimiter,keys(var.network)[count.index])[1] : keys(var.network)[count.index]
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_virtual_machine" "template" {
count = var.content_library == null ? 1 : 0
name = var.vmtemp
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_content_library" "library" {
count = var.content_library != null ? 1 : 0
name = var.content_library
depends_on = [var.tag_depends_on]
}
data "vsphere_content_library_item" "library_item_template" {
count = var.content_library != null ? 1 : 0
library_id = data.vsphere_content_library.library[0].id
type = "ovf"
name = var.vmtemp
depends_on = [var.tag_depends_on]
}
data "vsphere_tag_category" "category" {
count = var.tags != null ? length(var.tags) : 0
name = keys(var.tags)[count.index]
depends_on = [var.tag_depends_on]
}
data "vsphere_tag" "tag" {
count = var.tags != null ? length(var.tags) : 0
name = var.tags[keys(var.tags)[count.index]]
category_id = data.vsphere_tag_category.category[count.index].id
depends_on = [var.tag_depends_on]
}
data "vsphere_folder" "folder" {
count = var.vmfolder != null ? 1 : 0
path = "/${data.vsphere_datacenter.dc.name}/vm/${var.vmfolder}"
depends_on = [var.vm_depends_on]
}
locals {
interface_count = length(var.ipv4submask) #Used for Subnet handeling
template_disk_count = var.content_library == null ? length(data.vsphere_virtual_machine.template[0].disks) : 0
}
// Cloning a Linux or Windows VM from a given template.
resource "vsphere_virtual_machine" "vm" {
count = var.instances
depends_on = [var.vm_depends_on]
name = "${var.staticvmname != null ? var.staticvmname : format("${var.vmname}${var.vmnameformat}", count.index + var.vmstartcount)}${var.fqdnvmname == true ? ".${var.domain}" : ""}"
resource_pool_id = var.vmrp != "" ? data.vsphere_resource_pool.pool[0].id : var.vmrpid
folder = var.vmfolder
tags = var.tag_ids != null ? var.tag_ids : data.vsphere_tag.tag[*].id
custom_attributes = var.custom_attributes
annotation = var.annotation
extra_config = var.extra_config
firmware = var.content_library == null && var.firmware == null ? data.vsphere_virtual_machine.template[0].firmware : var.firmware
efi_secure_boot_enabled = var.content_library == null && var.efi_secure_boot == null ? data.vsphere_virtual_machine.template[0].efi_secure_boot_enabled : var.efi_secure_boot
enable_disk_uuid = var.content_library == null && var.enable_disk_uuid == null ? data.vsphere_virtual_machine.template[0].enable_disk_uuid : var.enable_disk_uuid
storage_policy_id = var.storage_policy_id
datastore_cluster_id = var.datastore_cluster != "" ? data.vsphere_datastore_cluster.datastore_cluster[0].id : null
datastore_id = var.datastore != "" ? data.vsphere_datastore.datastore[0].id : null
num_cpus = var.cpu_number
num_cores_per_socket = var.num_cores_per_socket
cpu_hot_add_enabled = var.cpu_hot_add_enabled
cpu_hot_remove_enabled = var.cpu_hot_remove_enabled
cpu_reservation = var.cpu_reservation
cpu_share_level = var.cpu_share_level
cpu_share_count = var.cpu_share_level == "custom" ? var.cpu_share_count : null
memory_reservation = var.memory_reservation
memory = var.ram_size
memory_hot_add_enabled = var.memory_hot_add_enabled
memory_share_level = var.memory_share_level
memory_share_count = var.memory_share_level == "custom" ? var.memory_share_count : null
guest_id = var.content_library == null ? data.vsphere_virtual_machine.template[0].guest_id : null
scsi_bus_sharing = var.scsi_bus_sharing
scsi_type = var.scsi_type != "" ? var.scsi_type : (var.content_library == null ? data.vsphere_virtual_machine.template[0].scsi_type : null)
scsi_controller_count = max(
max(0, flatten([
for item in values(var.data_disk) : [
for elem, val in item :
elem == "data_disk_scsi_controller" ? val : 0
]])...) + 1,
ceil((max(0, flatten([
for item in values(var.data_disk) : [
for elem, val in item :
elem == "unit_number" ? val : 0
]])...) + 1) / 15),
var.scsi_controller)
wait_for_guest_net_routable = var.wait_for_guest_net_routable
wait_for_guest_ip_timeout = var.wait_for_guest_ip_timeout
wait_for_guest_net_timeout = var.wait_for_guest_net_timeout
ignored_guest_ips = var.ignored_guest_ips
dynamic "network_interface" {
for_each = keys(var.network) #data.vsphere_network.network[*].id #other option
content {
network_id = data.vsphere_network.network[network_interface.key].id
adapter_type = var.network_type != null ? var.network_type[network_interface.key] : (var.content_library == null ? data.vsphere_virtual_machine.template[0].network_interface_types[0] : null)
}
}
// Disks defined in the original template
dynamic "disk" {
for_each = var.content_library == null ? data.vsphere_virtual_machine.template[0].disks : []
iterator = template_disks
content {
label = length(var.disk_label) > 0 ? var.disk_label[template_disks.key] : "disk${template_disks.key}"
size = var.disk_size_gb != null ? var.disk_size_gb[template_disks.key] : data.vsphere_virtual_machine.template[0].disks[template_disks.key].size
unit_number = var.scsi_controller != null ? var.scsi_controller * 15 + template_disks.key : template_disks.key
thin_provisioned = data.vsphere_virtual_machine.template[0].disks[template_disks.key].thin_provisioned
eagerly_scrub = data.vsphere_virtual_machine.template[0].disks[template_disks.key].eagerly_scrub
datastore_id = var.disk_datastore != "" ? data.vsphere_datastore.disk_datastore[0].id : null
storage_policy_id = length(var.template_storage_policy_id) > 0 ? var.template_storage_policy_id[template_disks.key] : null
io_reservation = length(var.io_reservation) > 0 ? var.io_reservation[template_disks.key] : null
io_share_level = length(var.io_share_level) > 0 ? var.io_share_level[template_disks.key] : "normal"
io_share_count = length(var.io_share_level) > 0 && var.io_share_level[template_disks.key] == "custom" ? var.io_share_count[template_disks.key] : null
}
}
// Disk for template from Content Library
dynamic "disk" {
for_each = var.content_library == null ? [] : [1]
iterator = template_disks
content {
label = length(var.disk_label) > 0 ? var.disk_label[template_disks.key] : "disk${template_disks.key}"
size = var.disk_size_gb[template_disks.key]
unit_number = var.scsi_controller != null ? var.scsi_controller * 15 + template_disks.key : template_disks.key
// thin_provisioned = data.vsphere_virtual_machine.template[0].disks[template_disks.key].thin_provisioned
// eagerly_scrub = data.vsphere_virtual_machine.template[0].disks[template_disks.key].eagerly_scrub
datastore_id = var.disk_datastore != "" ? data.vsphere_datastore.disk_datastore[0].id : null
storage_policy_id = length(var.template_storage_policy_id) > 0 ? var.template_storage_policy_id[template_disks.key] : null
io_reservation = length(var.io_reservation) > 0 ? var.io_reservation[template_disks.key] : null
io_share_level = length(var.io_share_level) > 0 ? var.io_share_level[template_disks.key] : "normal"
io_share_count = length(var.io_share_level) > 0 && var.io_share_level[template_disks.key] == "custom" ? var.io_share_count[template_disks.key] : null
disk_mode = length(var.disk_mode) > 0 ? var.disk_mode[template_disks.key] : null
}
}
// Additional disks defined by Terraform config
dynamic "disk" {
for_each = var.data_disk
iterator = terraform_disks
content {
label = terraform_disks.key
size = lookup(terraform_disks.value, "size_gb", null)
unit_number = (
lookup(
terraform_disks.value,
"unit_number",
-1
) < 0 ? (
lookup(
terraform_disks.value,
"data_disk_scsi_controller",
0
) > 0 ? (
(terraform_disks.value.data_disk_scsi_controller * 15) +
index(keys(var.data_disk), terraform_disks.key) +
(var.scsi_controller == tonumber(terraform_disks.value["data_disk_scsi_controller"]) ? local.template_disk_count : 0)
) : (
index(keys(var.data_disk), terraform_disks.key) + local.template_disk_count
)
) : (
tonumber(terraform_disks.value["unit_number"])
)
)
thin_provisioned = lookup(terraform_disks.value, "thin_provisioned", "true")
eagerly_scrub = lookup(terraform_disks.value, "eagerly_scrub", "false")
datastore_id = lookup(terraform_disks.value, "datastore_id", null)
storage_policy_id = lookup(terraform_disks.value, "storage_policy_id", null)
io_reservation = lookup(terraform_disks.value, "io_reservation", null)
io_share_level = lookup(terraform_disks.value, "io_share_level", "normal")
io_share_count = lookup(terraform_disks.value, "io_share_level", null) == "custom" ? lookup(terraform_disks.value, "io_share_count") : null
disk_mode = lookup(terraform_disks.value, "disk_mode", null)
disk_sharing = lookup(terraform_disks.value, "disk_sharing", null)
attach = lookup(terraform_disks.value, "attach", null)
path = lookup(terraform_disks.value, "path", null)
}
}
clone {
template_uuid = var.content_library == null ? data.vsphere_virtual_machine.template[0].id : data.vsphere_content_library_item.library_item_template[0].id
linked_clone = var.linked_clone
timeout = var.timeout
customize {
dynamic "linux_options" {
for_each = var.is_windows_image ? [] : [1]
content {
host_name = var.staticvmname != null ? var.staticvmname : format("${var.vmname}${var.vmnameformat}", count.index + var.vmstartcount)
domain = var.domain
hw_clock_utc = var.hw_clock_utc
}
}
dynamic "windows_options" {
for_each = var.is_windows_image ? [1] : []
content {
computer_name = var.staticvmname != null ? var.staticvmname : format("${var.vmname}${var.vmnameformat}", count.index + var.vmstartcount)
admin_password = var.local_adminpass
workgroup = var.workgroup
join_domain = var.windomain
domain_admin_user = var.domain_admin_user
domain_admin_password = var.domain_admin_password
organization_name = var.orgname
run_once_command_list = var.run_once
auto_logon = var.auto_logon
auto_logon_count = var.auto_logon_count
time_zone = var.time_zone
product_key = var.productkey
full_name = var.full_name
}
}
dynamic "network_interface" {
for_each = keys(var.network)
content {
ipv4_address = split("/", var.network[keys(var.network)[network_interface.key]][count.index])[0]
ipv4_netmask = var.network[keys(var.network)[network_interface.key]][count.index] == "" ? null : (
length(split("/", var.network[keys(var.network)[network_interface.key]][count.index])) == 2 ? (
split("/", var.network[keys(var.network)[network_interface.key]][count.index])[1]
) : (
length(var.ipv4submask) == 1 ? var.ipv4submask[0] : var.ipv4submask[network_interface.key]
)
)
}
}
dns_server_list = var.dns_server_list
dns_suffix_list = var.dns_suffix_list
ipv4_gateway = var.vmgateway
}
}
// Advanced options
hv_mode = var.hv_mode
ept_rvi_mode = var.ept_rvi_mode
nested_hv_enabled = var.nested_hv_enabled
enable_logging = var.enable_logging
cpu_performance_counters_enabled = var.cpu_performance_counters_enabled
swap_placement_policy = var.swap_placement_policy
latency_sensitivity = var.latency_sensitivity
shutdown_wait_timeout = var.shutdown_wait_timeout
force_power_off = var.force_power_off
}
================================================
FILE: output.tf
================================================
output "DC_ID" {
description = "id of vSphere Datacenter"
value = data.vsphere_datacenter.dc.id
}
output "ResPool_ID" {
description = "Resource Pool id"
value = var.vmrp != "" ? data.vsphere_resource_pool.pool[0].id : var.vmrpid
}
output "VM" {
description = "VM Names"
value = vsphere_virtual_machine.vm.*.name
}
output "ip" {
description = "default ip address of the deployed VM"
value = vsphere_virtual_machine.vm.*.default_ip_address
}
output "guest-ip" {
description = "all the registered ip address of the VM"
value = vsphere_virtual_machine.vm.*.guest_ip_addresses
}
output "uuid" {
description = "UUID of the VM in vSphere"
value = vsphere_virtual_machine.vm.*.uuid
}
output "disk" {
description = "Disks of the deployed VM"
value = vsphere_virtual_machine.vm.*.disk
}
================================================
FILE: tests/sanity/.terraform.lock.hcl
================================================
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/vsphere" {
version = "2.0.0"
hashes = [
"h1:kF5EuJgqGrd6fElgIGSk7NpipRAo7bUcBygIFOQmLz0=",
"zh:0c173a821b4e73b54474911b340220081c1ace68e02f58c076700ae0c6ec97cf",
"zh:0cf8b72fc5747591a23ffa72a667a14bbf1b1138f430b863b2b3724f45c10462",
"zh:262d2cc5510e18271022a650d537d09ab3037fe40812407b3dc31730d4c8159e",
"zh:2f1184a1a29b5b0b31baafb63314139842305894d2d235200562af474d69763f",
"zh:482f3e59a71d4ca8dcd3524459f09f0c14c5ef61990bd273e4dd4cfb930cb7ee",
"zh:4a7c1b37fcd7342d333b8970263fe89d813d0502b687cd1e2733cbb3e4ad4c97",
"zh:687b37b885b22bd7114b271fa999d483f993e120d0b8322cad7f907159b64c3a",
"zh:6dd70d4f7542f11449cb8fbfbd186d9da233243bee5f8005c804dc6afb418e84",
"zh:ab241bb083e077d40096e8ffe701dfbdf510cf6adb329af9c8c5231a48416b8f",
"zh:b53de1995cc493683c75f416b072069919e2ef3d297384412d9d8f8c7ac8de90",
"zh:e9b78cf4c133a7c9a05cec410cf468475c1c397c0a8b3ab5685c61e24ad02f68",
]
}
================================================
FILE: tests/sanity/README.md
================================================
# Sanity Test for new Functionality
**Copy of a TF Plan shoud be submmited with each PR, new functionality/variable should be explicitly added here under static values section in the main.tf file.**
### tfvars Example:
```hcl
viserver = "fill"
viuser = "fill"
vipassword = "fill"
vm = {
linuxvm = {
vmtemp = "Template name",
is_windows_image = false
vmrp = "fill"
dc = "fill",
datastore = "fill"
vmfolder = "fill"
vmgateway = "10.13.13.1"
dns_servers = ["1.1.1.1"]
network = {
"VM Port Group" = ["10.13.13.2", ""], # To use DHCP create Empty list for each instance
"VM Port Group" = ["", ""]
}
},
windowsvm = {
vmtemp = "fill"
is_windows_image = true
vmrp = "fill"
dc = "fill"
vmfolder = "fill"
datastore = "fill"
dns_servers = null
vmgateway = "10.13.13.1"
network = {
"VM Port Group" = ["10.13.13.2", ""], # To use DHCP create Empty list for each instance
"VM Port Group" = ["", ""]
}
}
}
```
================================================
FILE: tests/sanity/apply.sh
================================================
terraform init
terraform fmt
terraform validate
terraform apply -var-file="private.tfvars"
================================================
FILE: tests/sanity/cleanup.sh
================================================
terraform destroy -var-file=private.tfvars
rm terraform.tfstate terraform.tfstate.backup .terraform.lock.hcl
rm -rf .terraform
================================================
FILE: tests/sanity/connection.tf
================================================
variable "viuser" {}
variable "vipassword" {}
variable "viserver" {}
# Configure the VMware vSphere Provider
provider "vsphere" {
user = var.viuser
password = var.vipassword
vsphere_server = var.viserver
# if you have a self-signed cert
allow_unverified_ssl = true
}
================================================
FILE: tests/sanity/main.tf
================================================
# This workspace id to test the newly added functionality of the changes.
#
# Testing Tags
resource "vsphere_tag_category" "category" {
name = "terraform-test-category"
cardinality = "SINGLE"
description = "Managed by Terraform"
associable_types = [
"VirtualMachine",
"Datastore",
]
}
resource "vsphere_tag" "tag" {
name = "terraform-test-tag"
category_id = vsphere_tag_category.category.id
description = "Managed by Terraform"
}
#to test naming convention
variable "env" {
default = "dev"
}
#Do not add any new variables here unless it is sensitive
variable "vm" {
type = map(object({
vmname = string
vmtemp = string
dc = string
vmrp = string
vmfolder = string
datastore = string
is_windows_image = bool
network = map(list(string))
vmgateway = string
dns_servers = list(string)
}))
}
#add the new added function/variables here
module "example-server-basic" {
source = "../../"
for_each = var.vm
vmrp = each.value.vmrp
vmfolder = each.value.vmfolder
vmtemp = each.value.vmtemp
is_windows_image = each.value.is_windows_image
network = each.value.network
vmgateway = each.value.vmgateway
dc = each.value.dc
datastore = each.value.datastore
#starting of static values
instances = 2
vmstartcount = 5
vmnameformat = "%03d${var.env}"
domain = "somedomain.com"
fqdnvmname = true
vmname = "terraform-sanitytest"
annotation = "Terraform Sanity Test"
tag_depends_on = [vsphere_tag.tag.id]
tags = {
"terraform-test-category" = "terraform-test-tag",
}
data_disk = {
disk1 = {
size_gb = 30,
thin_provisioned = false,
data_disk_scsi_controller = 0,
storage_policy_id = "ff45cc66-b624-4621-967f-1aef6437f568"
},
disk2 = {
size_gb = 70,
thin_provisioned = true,
data_disk_scsi_controller = 1,
io_reservation = 15
io_share_level = "custom"
io_share_count = 2000
}
}
io_reservation = [15]
io_share_level = ["custom"]
io_share_count = [2000]
memory_share_level = "custom"
memory_share_count = 2000
cpu_share_level = "custom"
cpu_share_count = 2000
#ipv4submask = ["28", "26"]
}
output "DC_ID" {
value = tomap({
for k, i in module.example-server-basic : k => i.DC_ID
})
}
output "VM" {
value = tomap({
for k, i in module.example-server-basic : k => i.VM
})
}
================================================
FILE: tests/sanity/plan.sh
================================================
terraform init
terraform fmt
terraform validate
terraform plan -var-file="private.tfvars"
================================================
FILE: tests/smoke/.terraform.lock.hcl
================================================
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/vsphere" {
version = "1.24.2"
hashes = [
"h1:BEf8p0h+NYK0hu4dG8NloZtNaSw5nbMKsqwIZWdsIPk=",
"zh:01d8e13dac110466f946da1f14294f64b747f1fa6f2d107f7bc0f8db40624497",
"zh:06670e7baa2c2083afbe01b617aa72bcd2950830ecb66f01e743e361105e7b47",
"zh:17220222bdeeeb7575a51ebd556377e9f2157258eec945710e95ec1a597f8ec7",
"zh:2dfd808800c21a483e7401254d6dd817ec3f7d323525cd7a6d3919c81e30e686",
"zh:671befb1f724ffbc68c117d06619989eb4b62246896ad168384540d1acc7a0b6",
"zh:7d29d02d1c2f82a1c71e38aaa9daa23d4cccfc5d00c0c9ea1e2c36d98343e855",
"zh:98a8acafe6e38f7ad214b53826b2a9dc1f036cfb3833ba67c517eae2e4ea56c0",
"zh:a74fc725844da35ab73105e62b97efe717fb5c5f21554ee656d434e9803f20ad",
"zh:a7ab1a04902254e63dc2dc489e69343c2a53999e987114c932259884594da1ec",
"zh:df0beaef2d925771724cbf19747787f618c595c0712dc210b5581041691310e6",
]
}
================================================
FILE: tests/smoke/README.md
================================================
# Smoke Test
You need to run the plan using private.tfvars
### Example:
```hcl
viserver = "fill"
viuser = "fill"
vipassword = "fill"
vm = {
linuxvm = {
vmname = "example-server-linux",
vmtemp = "fill"
content_library = null
annotation = "Terraform Smoke Test"
instances = 0
is_windows_image = false
vmrp = "fill"
dc = "fill"
datastore = "fill"
vmfolder = "fill"
vmgateway = "10.13.13.1"
dns_servers = ["1.1.1.1"]
network = {
"VM Networks" = ["10.13.13.2"],
}
disk_size_gb = [ 20 ]
}
}
```
================================================
FILE: tests/smoke/apply.sh
================================================
terraform init
terraform fmt
terraform validate
terraform apply -var-file="private.tfvars"
================================================
FILE: tests/smoke/connection.tf
================================================
variable "viuser" {}
variable "vipassword" {}
variable "viserver" {}
# Configure the VMware vSphere Provider
provider "vsphere" {
user = var.viuser
password = var.vipassword
vsphere_server = var.viserver
# if you have a self-signed cert
allow_unverified_ssl = true
}
================================================
FILE: tests/smoke/main.tf
================================================
#######################################
# This workspace is for smoke test
# do not modify this file
# #####################################
variable "vm" {
type = map(object({
vmname = string
vmtemp = string
annotation = string
dc = string
vmrp = string
vmfolder = string
datastore = string
is_windows_image = bool
instances = number
network = map(list(string))
vmgateway = string
dns_servers = list(string)
}))
}
module "example-server-basic" {
source = "../../"
for_each = var.vm
vmtemp = each.value.vmtemp
annotation = each.value.annotation
is_windows_image = each.value.is_windows_image
instances = each.value.instances
vmname = each.value.vmname
vmrp = each.value.vmrp
vmfolder = each.value.vmfolder
network = each.value.network
vmgateway = each.value.vmgateway
dc = each.value.dc
datastore = each.value.datastore #Either
}
================================================
FILE: tests/smoke/plan.sh
================================================
terraform init
terraform fmt
terraform validate
terraform plan -var-file="private.tfvars"
================================================
FILE: variables.tf
================================================
#Network Section
variable "network" {
description = "Define PortGroup and IPs/CIDR for each VM. If no CIDR provided, the subnet mask is taken from var.ipv4submask."
type = map(list(string))
default = {}
}
variable "network_delimiter" {
description = "If network name needs a delimiter for sequencing, define an UNUSED character here, otherwise leave as null"
type = string
default = null
}
variable "network_type" {
description = "Define network type for each network interface."
type = list(any)
default = null
}
variable "ipv4submask" {
description = "ipv4 Subnet mask. Warning: The order must follow the alphabetic order from var.network."
type = list(any)
default = ["24"]
}
#Data Disk section
variable "datastore_cluster" {
description = "Datastore cluster to deploy the VM."
default = ""
}
variable "datastore" {
description = "Datastore to deploy the VM."
default = ""
}
variable "data_disk" {
description = "Storage data disk parameter, example"
type = map(map(string))
default = {}
}
variable "disk_label" {
description = "Storage data disk labels."
type = list(any)
default = []
}
variable "disk_size_gb" {
description = "List of disk sizes to override template disk size."
type = list(any)
default = null
}
variable "disk_datastore" {
description = "Define where the OS disk should be stored."
type = string
default = ""
}
variable "io_reservation" {
description = "The I/O reservation (guarantee) that this disk has, in IOPS. The default is no reservation."
type = list(number)
default = []
}
variable "io_share_level" {
description = "The share allocation level for this disk. Can be one of low, normal, high, or custom. Default: normal."
type = list(string)
default = ["normal"]
}
variable "io_share_count" {
description = "The share count for this disk when the share level is custom."
type = list(number)
default = []
}
variable "disk_mode" {
description = "The disk mode for the disk."
type = list(string)
default = []
}
variable "template_storage_policy_id" {
description = "List of UUIDs of the storage policy to assign to the template disk."
type = list(any)
default = []
}
variable "scsi_bus_sharing" {
description = "scsi_bus_sharing mode, acceptable values physicalSharing,virtualSharing,noSharing."
type = string
default = null
}
variable "scsi_type" {
description = "scsi_controller type, acceptable values lsilogic,pvscsi."
type = string
default = ""
}
variable "scsi_controller" {
description = "scsi_controller number for the main OS disk."
type = number
default = 0
# validation {
# condition = var.scsi_controller < 4 && var.scsi_controller > -1
# error_message = "The scsi_controller must be between 0 and 3"
# }
}
variable "enable_disk_uuid" {
description = "Expose the UUIDs of attached virtual disks to the virtual machine, allowing access to them in the guest. Default: Inherited from cloned template"
type = bool
default = null
}
variable "storage_policy_id" {
description = "(Optional) The UUID of the storage policy to assign to VM home directory."
default = null
}
###########################################
variable "vmname" {
description = "The name of the virtual machine used to deploy the vms. This name can scale out based on number of instances and vmnameformat - example can be found under exampel folder"
default = "terraformvm"
}
variable "vmnameformat" {
description = "vmname format. default is set to 2 decimal with leading 0. example: %03d for 3 decimal with leading zero or %02dprod for additional suffix"
default = "%02d"
}
variable "vmstartcount" {
description = "vmname start count value. default is set to 1. example: a value of 4 (with default format and 2 instances) will make first instance suffix 04 and second instance suffix 05"
default = 1
}
variable "staticvmname" {
description = "Static name of the virtual machin. When this option is used VM can not scale out using instance variable. You can use for_each outside the module to deploy multiple static vms with different names"
default = null
}
variable "fqdnvmname" {
description = "If true, the vm will be created using domain variable appended"
type = bool
default = false
}
variable "vmtemp" {
description = "Name of the template available in the vSphere."
}
variable "content_library" {
description = "Name of the content library where the OVF template is stored."
default = null
}
variable "instances" {
description = "number of instances you want deploy from the template."
default = 1
}
variable "cpu_number" {
description = "number of CPU (core per CPU) for the VM."
default = 2
}
variable "cpu_reservation" {
description = "The amount of CPU (in MHz) that this virtual machine is guaranteed."
default = null
}
variable "cpu_share_level" {
description = "The allocation level for CPU resources. Can be one of high, low, normal, or custom. Default: custom."
type = string
default = "normal"
}
variable "cpu_share_count" {
description = "The number of CPU shares allocated to the virtual machine when the cpu_share_level is custom."
type = number
default = 4000
}
variable "ram_size" {
description = "VM RAM size in megabytes."
default = 4096
}
variable "dc" {
description = "Name of the datacenter you want to deploy the VM to."
}
variable "vmrpid" {
description = "ID of cluster resource pool that VM will be deployed to. you use following to choose default pool in the cluster (esxi1) or (Cluster)/Resources."
default = ""
}
variable "vmrp" {
description = "Cluster resource pool that VM will be deployed to. you use following to choose default pool in the cluster (esxi1) or (Cluster)/Resources."
default = ""
}
variable "vmfolder" {
description = "The path to the folder to put this virtual machine in, relative to the datacenter that the resource pool is in. Path - The absolute path of the folder. For example, given a default datacenter of default-dc, a folder of type vm, and a folder name of terraform-test-folder, the resulting path would be /default-dc/vm/terraform-test-folder."
default = null
}
variable "vmgateway" {
description = "VM gateway to set during provisioning."
default = null
}
variable "dns_server_list" {
type = list(string)
default = null
}
#Global Customization Variables
variable "tags" {
description = "The names of any tags to attach to this resource. They must already exist."
type = map(any)
default = null
}
variable "tag_ids" {
description = "The ids of any tags to attach to this resource. They must already exist."
type = list(any)
default = null
}
variable "custom_attributes" {
description = "Map of custom attribute ids to attribute value strings to set for virtual machine."
type = map(any)
default = null
}
variable "extra_config" {
description = "Extra configuration data for this virtual machine. Can be used to supply advanced parameters not normally in configuration, such as instance metadata.'disk.enableUUID', 'True'."
type = map(any)
default = null
}
variable "annotation" {
description = "A user-provided description of the virtual machine. The default is no annotation."
default = null
}
variable "linked_clone" {
description = "Clone this virtual machine from a snapshot. Templates must have a single snapshot only in order to be eligible."
default = false
}
variable "timeout" {
description = "The timeout, in minutes, to wait for the virtual machine clone to complete."
type = number
default = 30
}
variable "dns_suffix_list" {
description = "A list of DNS search domains to add to the DNS configuration on the virtual machine."
type = list(string)
default = null
}
variable "firmware" {
description = "The firmware interface to use on the virtual machine. Can be one of bios or EFI. Default: Inherited from cloned template"
default = null
}
variable "efi_secure_boot" {
description = "Enables EFI secure boot. Can be only be true when firmware is EFI. Default: Inherited from cloned template"
default = null
}
variable "num_cores_per_socket" {
description = "The number of cores to distribute among the CPUs in this virtual machine. If specified, the value supplied to num_cpus must be evenly divisible by this value."
type = number
default = 1
}
variable "cpu_hot_add_enabled" {
description = "Allow CPUs to be added to this virtual machine while it is running."
type = bool
default = null
}
variable "cpu_hot_remove_enabled" {
description = "Allow CPUs to be removed to this virtual machine while it is running."
type = bool
default = null
}
variable "memory_hot_add_enabled" {
description = "Allow memory to be added to this virtual machine while it is running."
type = bool
default = null
}
variable "memory_reservation" {
description = "The amount of memory (in MB) that this virtual machine is guaranteed."
default = null
}
variable "memory_share_level" {
description = "The allocation level for memory resources. Can be one of high, low, normal, or custom"
type = string
default = "normal"
}
variable "memory_share_count" {
description = "(Optional) The number of memory shares allocated to the virtual machine when the memory_share_level is custom"
type = number
default = 81920
}
#Linux Customization Variables
variable "hw_clock_utc" {
description = "Tells the operating system that the hardware clock is set to UTC."
type = bool
default = true
}
variable "domain" {
description = "default VM domain for linux guest customization and fqdn name (if fqdnvmname is true)."
default = "Development.com"
}
#Windows Customization Variables
variable "is_windows_image" {
description = "Boolean flag to notify when the custom image is windows based."
type = bool
default = false
}
variable "local_adminpass" {
description = "The administrator password for this virtual machine.(Required) when using join_windomain option."
default = null
}
variable "workgroup" {
description = "The workgroup name for this virtual machine. One of this or join_domain must be included."
default = null
}
variable "windomain" {
description = "The domain to join for this virtual machine. One of this or workgroup must be included."
default = null
}
variable "domain_admin_user" {
description = "Domain admin user to join the server to AD.(Required) when using join_windomain option."
default = null
}
variable "domain_admin_password" {
description = "Doamin User pssword to join the server to AD.(Required) when using join_windomain option."
default = null
}
variable "orgname" {
description = "Organization name for when joining windows server to AD."
default = null
}
variable "auto_logon" {
description = " Specifies whether or not the VM automatically logs on as Administrator. Default: false."
type = bool
default = null
}
variable "auto_logon_count" {
description = "Specifies how many times the VM should auto-logon the Administrator account when auto_logon is true. This should be set accordingly to ensure that all of your commands that run in run_once_command_list can log in to run."
default = null
}
variable "time_zone" {
description = "The new time zone for the virtual machine. This is a numeric, sysprep-dictated, timezone code."
default = null
}
variable "run_once" {
description = "List of Comamnd to run during first logon (Automatic login set to 1)."
type = list(string)
default = null
}
variable "productkey" {
description = "Product key to be used during windows customization."
default = null
}
variable "full_name" {
description = "The full name of the user of this virtual machine. This populates the user field in the general Windows system information. Default - Administrator."
default = null
}
variable "wait_for_guest_net_routable" {
description = "Controls whether or not the guest network waiter waits for a routable address. When false, the waiter does not wait for a default gateway, nor are IP addresses checked against any discovered default gateways as part of its success criteria. This property is ignored if the wait_for_guest_ip_timeout waiter is used."
type = bool
default = true
}
variable "wait_for_guest_ip_timeout" {
description = "The amount of time, in minutes, to wait for an available guest IP address on this virtual machine. This should only be used if your version of VMware Tools does not allow the wait_for_guest_net_timeout waiter to be used. A value less than 1 disables the waiter."
type = number
default = 0
}
variable "wait_for_guest_net_timeout" {
description = "The amount of time, in minutes, to wait for an available IP address on this virtual machine's NICs. Older versions of VMware Tools do not populate this property. In those cases, this waiter can be disabled and the wait_for_guest_ip_timeout waiter can be used instead. A value less than 1 disables the waiter."
type = number
default = 5
}
variable "ignored_guest_ips" {
description = "List of IP addresses and CIDR networks to ignore while waiting for an available IP address using either of the waiters. Any IP addresses in this list will be ignored if they show up so that the waiter will continue to wait for a real IP address."
type = list(string)
default = []
}
variable "vm_depends_on" {
description = "Add any external depend on module here like vm_depends_on = [module.fw_core01.firewall]."
type = any
default = null
}
variable "tag_depends_on" {
description = "Add any external depend on module here like tag_depends_on = [vsphere_tag.foo.id]."
type = any
default = null
}
variable "hv_mode" {
description = "The (non-nested) hardware virtualization setting for this virtual machine. Can be one of hvAuto, hvOn, or hvOff."
type = string
default = null
}
variable "ept_rvi_mode" {
description = "The EPT/RVI (hardware memory virtualization) setting for this virtual machine."
type = string
default = null
}
variable "nested_hv_enabled" {
description = "Enable nested hardware virtualization on this virtual machine, facilitating nested virtualization in the guest."
type = bool
default = null
}
variable "enable_logging" {
description = "Enable logging of virtual machine events to a log file stored in the virtual machine directory."
type = bool
default = null
}
variable "cpu_performance_counters_enabled" {
description = "Enable CPU performance counters on this virtual machine."
type = bool
default = null
}
variable "swap_placement_policy" {
description = "The swap file placement policy for this virtual machine. Can be one of inherit, hostLocal, or vmDirectory."
type = string
default = null
}
variable "latency_sensitivity" {
description = "Controls the scheduling delay of the virtual machine. Use a higher sensitivity for applications that require lower latency, such as VOIP, media player applications, or applications that require frequent access to mouse or keyboard devices.Can be one of low, normal, medium, or high."
type = string
default = null
}
variable "shutdown_wait_timeout" {
description = "The amount of time, in minutes, to wait for a graceful guest shutdown when making necessary updates to the virtual machine. If force_power_off is set to true, the VM will be force powered-off after this timeout, otherwise an error is returned."
type = string
default = null
}
variable "migrate_wait_timeout" {
description = "The amount of time, in minutes, to wait for a graceful guest shutdown when making necessary updates to the virtual machine. If force_power_off is set to true, the VM will be force powered-off after this timeout, otherwise an error is returned."
type = string
default = null
}
variable "force_power_off" {
description = "If a guest shutdown failed or timed out while updating or destroying (see shutdown_wait_timeout), force the power-off of the virtual machine."
type = bool
default = null
}
================================================
FILE: versions.tf
================================================
terraform {
required_version = ">= 0.13.4"
required_providers {
vsphere = {
source = "hashicorp/vsphere"
}
}
}
gitextract_pni6tlpg/ ├── .github/ │ └── stale.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── examples/ │ ├── README.md │ ├── example-Windows-data_disk.tf │ ├── example-linux-Network.tf │ ├── example-linux-depend_on.tf │ └── example-vmname.tf ├── main.tf ├── output.tf ├── tests/ │ ├── sanity/ │ │ ├── .terraform.lock.hcl │ │ ├── README.md │ │ ├── apply.sh │ │ ├── cleanup.sh │ │ ├── connection.tf │ │ ├── main.tf │ │ └── plan.sh │ └── smoke/ │ ├── .terraform.lock.hcl │ ├── README.md │ ├── apply.sh │ ├── connection.tf │ ├── main.tf │ └── plan.sh ├── variables.tf └── versions.tf
Condensed preview — 28 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (67K chars).
[
{
"path": ".github/stale.yml",
"chars": 688,
"preview": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 30\n# Number of days of inactivity before a "
},
{
"path": ".gitignore",
"chars": 158,
"preview": "# Local .terraform directories\n**/.terraform/*\n\n# .tfstate files\n*.tfstate\n*.tfstate.*\n\n# .tfvars files\n*.tfvars\n\n#Sens"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3347,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "CONTRIBUTING.md",
"chars": 2362,
"preview": "# Contributing to terraform-vsphere-vm\nWe love your input! We want to make contributing to this project as easy and tran"
},
{
"path": "LICENSE",
"chars": 1094,
"preview": "MIT License\n\nCopyright (c) Microsoft Corporation. All rights reserved.\n\nPermission is hereby granted, free of charge, to"
},
{
"path": "README.md",
"chars": 6503,
"preview": "# Terraform vSphere Module\n\n [. The extraction includes 28 files (61.6 KB), approximately 16.7k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.