Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FeatureRequest] Cloud-Init support #36

Open
piotrkochan opened this issue Oct 11, 2020 · 11 comments
Open

[FeatureRequest] Cloud-Init support #36

piotrkochan opened this issue Oct 11, 2020 · 11 comments

Comments

@piotrkochan
Copy link

piotrkochan commented Oct 11, 2020

It would be greet bo be able to use cloud-init to automate many stuff inside created vm

Affected Resource(s)

hyperv_machine_instance

Expected Behavior

data "template_file" "user_data" {
  template = file("cloud-init/test.yml")
}
resource "hyperv_machine_instance" "kube1" {
...
user_data = data.template_file.user_data.rendered
...
}

cloud-init/test.yml:

users:
  - default
  - name: terraform
    gecos: terraform
    primary_group: hashicorp
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: users, admin
    ssh_import_id:
    lock_passwd: false
    ssh_authorized_keys:
      ...

Actual Behavior

What actually happened?

╭─kochan@AORUS ~/github/infra/terraform-provider-hyperv/examples/basic ‹master*›
╰─$ terraform plan -out=tfplan

Error: Unsupported argument

  on main.tf line 43, in resource "hyperv_machine_instance" "kube1":
  43:   user_data = data.template_file.user_data.rendered

An argument named "user_data" is not expected here.
@taliesins
Copy link
Owner

@taliesins
Copy link
Owner

Might also be able to achieve this by starting a web server and serving the contents like Packer.

See:

@shuguet
Copy link
Contributor

shuguet commented Feb 7, 2021

Hello @taliesins,

Is there any chance to get this implemented sooner? Would tipping/sponsoring you help?

Happy to do so, I could really use the cloud-init support on Hyper-V for a personal project

@lexfrei
Copy link

lexfrei commented Jun 22, 2022

Any news on this?

@chazragg
Copy link
Contributor

chazragg commented Dec 7, 2023

After some reserach is seems a lot of people opt to pass the cloud-init files through DVD to hyper-v VMs, i am not too familar with cloud-init but i am unsure if it would work through the http method that packer employs as the configuration happens at a boot level before any networking is active

you should be able to provide a list of files from the cloud-init provider to a user-data field under vm-instance and have it generate into an iso and mount to the VM on startup maybe also a toggle if you want this to happen only on first creation or every time an update happens.

if i get some time i will try look into this but my go skills are a bit rusty.

@chazragg
Copy link
Contributor

So I had some free time and proved a bit of a PoC

I am currently looking into a packer - ansible - terraform - cloud-init setup for hyper-v

I've created a small tool with Go to convert a folder of files into an ISO, I believe the provider could benefit from this as we could read a folder from the user_data or cloud_init field to the vm_isntance resource

My process is the following:

  • Packer builds a golden image using rocky Linux and a Kickstarter file that installs deps like ansible, cloud-init, etc, etc
  • packer ansible provisioners then applies some devsec OS hardening to the image to keep it compliant
  • this produces an iso or a .zip
  • Terraform consumes the iso/.zip
  • (manual step) I created a small go program to add some files to an iso
  • Terraform mounts the iso to a virtual disk drive on the VM
  • On VM boot it spins up and provisions the hostname an IP address + anything else we want at that time
  • Terraform ansible provider provisions the rest

The next step is just to add the conversion and mount the iso to the VM into the provider as this would allow you to use the cloud-init providers to incorporate templating so the process would be

  • Generate cloud-init template
  • Pass it through the user_data field on the VM resource
  • covert that template into an iso and mount it to the VM

You need cloud-init installed in the base image obviously but most OS images have a generic cloud image you can use.

@taliesins
Copy link
Owner

Hey guys I had some free time over the holidays. Hopefully #235 will enable an avenue for running cloud-init

@chazragg
Copy link
Contributor

chazragg commented Jan 4, 2024

I started some work on this myself but my knowledge of go and Terraform modules is limited. it will be interesting to compare the results with my hacky code 👍

@fsdrw08
Copy link
Contributor

fsdrw08 commented Jan 11, 2024

I make a terraform module to perform an cloud-init required format ISO, the main process is use null_resource + local-exec to run some local commands to create an ISO file match cloud-init's requirement.
https://github.com/fsdrw08/SoloLab/tree/main/TerraformWorkShop/Hyper-V/modules/cloudinit_nocloud_iso2

some example
https://github.com/fsdrw08/SoloLab/blob/main/TerraformWorkShop/Hyper-V/VM-Dev-Fedora/main.tf

@taliesins
Copy link
Owner

@fsdrw08 you have an impressive repo there :>. Do you take requests, I would like to put together a few good demos for the most common use cases. Ubuntu, Windows with cloud init and perhaps a static ip and running maybe Ansible against it (so bootstrapping).

The newly added functionality should hopefully get rid of the need for null resource provider:
https://github.com/taliesins/terraform-provider-hyperv/blob/master/examples/resources/hyperv_iso_image/resource.tf#L19

resource "hyperv_iso_image" "bootstrap" {
  volume_name               = "BOOTSTRAP"
  source_zip_file_path      = data.archive_file.bootstrap.output_path
  source_zip_file_path_hash = data.archive_file.bootstrap.output_sha
  destination_iso_file_path = "$env:TEMP\\bootstrap.iso"
  iso_media_type            = "dvdplusrw_duallayer"
  iso_file_system_type      = "unknown"
}

The most difficult part for me to wrap my head around was the update logic (would not mind anyone else having a look at this):
https://github.com/taliesins/terraform-provider-hyperv/blob/master/internal/provider/resource_hyperv_iso_image.go#L322

@fsdrw08
Copy link
Contributor

fsdrw08 commented Jan 19, 2024

@fsdrw08 you have an impressive repo there :>. Do you take requests, I would like to put together a few good demos for the most common use cases. Ubuntu, Windows with cloud init and perhaps a static ip and running maybe Ansible against it (so bootstrapping).

The newly added functionality should hopefully get rid of the need for null resource provider: https://github.com/taliesins/terraform-provider-hyperv/blob/master/examples/resources/hyperv_iso_image/resource.tf#L19

resource "hyperv_iso_image" "bootstrap" {
  volume_name               = "BOOTSTRAP"
  source_zip_file_path      = data.archive_file.bootstrap.output_path
  source_zip_file_path_hash = data.archive_file.bootstrap.output_sha
  destination_iso_file_path = "$env:TEMP\\bootstrap.iso"
  iso_media_type            = "dvdplusrw_duallayer"
  iso_file_system_type      = "unknown"
}

The most difficult part for me to wrap my head around was the update logic (would not mind anyone else having a look at this): https://github.com/taliesins/terraform-provider-hyperv/blob/master/internal/provider/resource_hyperv_iso_image.go#L322

Here is an example which might meet your request, https://github.com/fsdrw08/SoloLab/blob/main/TerraformWorkShop/Hyper-V/VM-InfraSvc-CentOS/main.tf
It contains the static IP config in cloudinit https://github.com/fsdrw08/SoloLab/blob/main/TerraformWorkShop/Hyper-V/VM-InfraSvc-CentOS/main.tf#L149
and the ansible config in cloudinit: https://github.com/fsdrw08/SoloLab/blob/main/TerraformWorkShop/Hyper-V/VM-InfraSvc-CentOS/main.tf#L122-L137

What I need is convert the cloud-init module to the hyperv_iso_image resource

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants