dmacvicar / terraform-provider-libvirt

Terraform provider to provision infrastructure with Linux's KVM using libvirt
Apache License 2.0
1.54k stars 457 forks source link

Allow provider configuration to be passed by its caller #1052

Open chanster opened 6 months ago

chanster commented 6 months ago

System Information

Linux distribution

Ubuntu 22.04

Terraform version

v1.6.4

Provider and libvirt versions

libvirt 0.7.6

Checklist

Description of Issue/Question

When calling libvirt resources within a module, it does not support the provider configuration provided by the caller. Having a module to create virtual machines provides a easy way to create them in mass rather than creating multiple similar resources at the root configuration.

lets say I have a module machine in {working_dir}/machine:

Setup

main.tf:

terraform {
  required_providers {
    libvirt = {
      source  = "registry.terraform.io/dmacvicar/libvirt"
      version = "0.7.6"
    }
  }
}

provider "libvirt" {
  uri = "qemu:///session"
}

module "vm" {
  source = "./machine"
  count  = 3
  name   = vm[count.index]
  ...
}

./machine/main.tf:

terraform {
  required_providers {
    libvirt = {
      source  = "registry.terraform.io/dmacvicar/libvirt"
      version = "0.7.6"
    }
  }
}

provider "libvirt" {
  uri = "qemu:///session"
}

resource "libvirt_volume" "root" {
  name           = "${var.name}.qcow2"
  source         = var.vm_image
  size           = 10 * 1024 * 1024 * 1024 # convert GB to bytes
  pool           = var.pool_name
}

resource "libvirt_domain" "main" {
  name = var.name
  vcpu = var.cpus

  cpu {
    mode = "host-passthrough"
  }

  network_interface {
    network_id     = var.network_id
    hostname       = var.hostname == null ? var.name : var.hostname
    addresses      = [var.ip_address]
    wait_for_lease = false
  }

  disk {
    volume_id = libvirt_volume.root.id
    scsi      = "true"
  }
}

Steps to Reproduce Issue

  1. Create a module that uses libvirt provider.
  2. Call the module created from terraform root configuration.
  3. run terraform init

    terraform init
    
    Initializing the backend...
    Initializing modules...
    ╷
    │ Error: Module is incompatible with count, for_each, and depends_on
    │ 
    │   on machines.tf line 16, in module "vm":
    │    16:   count = 3
    │ 
    │ The module at module.machine is a legacy module which contains its own local provider configurations, and so calls to it may not use the count, for_each, or depends_on arguments.
    │ 
    │ If you also control the module "./machine", consider updating this module to instead expect provider configurations to be passed by its caller.
  4. removing provider block from ./machines/main.tf allows module to work but no longer runs with correct context of qemu:///session, and defaults to qemu:///system.
    # removed this block
    provider "libvirt" {
      uri = "qemu:///session"
    }
  5. Removing terraform block from ./machines/main.tf causes module not correctly resolve.
    │ Error: Failed to query available provider packages
    │ 
    │ Could not retrieve the list of available versions for provider hashicorp/libvirt: provider registry registry.terraform.io does not have a provider named registry.terraform.io/hashicorp/libvirt
    │ 
    │ Did you intend to use dmacvicar/libvirt? If so, you must specify that source address in each module which requires that provider. To see which modules are currently depending on hashicorp/libvirt, run the following
    │ command:
    │     terraform providers

Additional information:

Do you have SELinux or Apparmor/Firewall enabled? Some special configuration? No Have you tried to reproduce the issue without them enabled? n/a

memetb commented 4 months ago

I am working on a PR for this (@dmacvicar)

I too see an important need for this: when writing modules, I may make use of virsh on multiple bare metal nodes to accomplish one orchestration event. I should not know as the caller that there are more than one endpoints.