Foreman provider for Terraform
Clone or download
mattwilmott Merge pull request #2 from jnahelou/fix.type_assignment
Some assignments are broken and cause compilation error
Latest commit 9aa0472 May 19, 2017


Foreman provider for Terraform (formerly terraform-foreman)

Note, I'm a DevOps Engineer who has come from a predominately Ops world. I have never written in Go previously instead prefering Ruby, Python, Javascript, Java or Bash. Hence this code may actually be completely wrong! Use this at your own risk! If you'd like to contribute please do, see the instructions below!

What is Terraform

Terraform is an orchestration tool that can be used to deploy and manage the lifecycle of cloud resources such as virtual machines, DNS records etc. That probably isn't giving it enough credit so check it out at

What is Foreman

Foreman (or more accurately TheForeman) is a Red Hat sponsored open source tool used to manage infrastructure in a Private Cloud. Foreman can provision for instance Docker instances, Virtual Machines in OpenStack or VMWare and it can even deploy to bare metal. Foreman ties into PuppetLabs Puppet infrastructure and provides ENC data regarding the servers it manages. Check it out at


Install terraform first using the instructions at

Add the following to your ~/.terraformrc

providers {
     foreman = "/path/to/bin/terraform-provider-foreman"

Sample terraform config. Save this as a or similar

provider "foreman" {
	username = "myusername"
	password = "mypassword"
	url = "https://my-foreman.fqdn"

resource "foreman_dns" "example" {
	host = ""

resource "foreman_server" "example" {
    name = "host${count.index}"
    location_id = 1
    organization_id = 1
    puppet_class_ids = ["1","2","3"]
    count = 3

resource "foreman_server" "complex_VM" {
    name = ""
    location_id = 1		# ID of foreman location, if locations are enabled
    organization_id = 2		# ID of foreman organization, if orgs are enabled
    environment_id = 4		# ID of foreman environment
    ip = ""
    mac = "00:50:56:8f:29:73"
    architecture_id = 1 	# x86_64
    domain_id = 1		# "First foreman domain"
    puppet_proxy_id = 2		# ID of your puppet master defined in foreman
    puppet_class_ids = ["351"]  # Puppet class ids
    operatingsystem_id = 1	# ID of a foreman operating system
    medium_id = 7		# ID of a foreman repository
    ptable_id = 3		# ID of a foreman partition table
    subnet_id = 3		# ID of a foreman subnet
    compute_resource_id = 1	# ID of a foreman compute resource, for example vCenter, docker, openstack nova
    model_id = 1		# ID of a foreman compute model
    owner_id = 17		# ID of a foreman user, likely that of the service account used to create it
    puppet_ca_proxy_id = 2	# ID of your puppet CA master defined in foreman
    build = false		# Build mode, determines if the PXE configs are generated by foreman
    enabled = true		# Enabled?? NFI
    provision_method = "build"  
    managed = true		
    comment = ""

resource "foreman_server" "myVM" {
  name = "hostname"
  environment_id = "environment_id"
  ip = ""
  mac	= "ff:ff:ff:ff:ff:ff"
  architecture_id = 1
  domain_id = 1
  realm_id = 1
  puppet_proxy_id	= 1
  puppetclass_ids	= [1,2,3]
  operatingsystem_id = 1
  medium_id = "1" # yeah, it's a string. idk, don't ask
  ptable_id	= 1
  subnet_id	= 1
  compute_resource_id	= 25
  root_pass	= "Superawesomehash"
  model_id = 1
  hostgroup_id = 1
  owner_id = 1
  owner_type = "User" # must be either User or Usergroup
  puppet_ca_proxy_id = 1
  image_id = 1
  build	= true
  enabled	= true
  provision_method = "build"
  managed	= true
  progress_report_id = "progress_report_id"
  comment = "Build purpose"
  capabilities = "Something"
  compute_profile_id = 1
	host_parameters_attributes {
    roles = "server_role"
    puppet = "true"
    chef = "false"
    mac = "ff:ff:ff:ff:ff:ff"
    ip = "ip"
    name = "name"
    subnet_id = 1
    domain_id = 1
    identifier = "identifier"
    managed = true
    primary = true
    provision = true
    username = "username" # only for bmc
    password = "password" # only for bmc
    provider = "provider" # only accepted IPMI
    virtual = false
    tag = "tag"
    attached_to = "something"
    mode = "mode" # with validations
    attached_devices 	=	[]string
    bond_options = "bond opts"
  compute_attributes {
    	cpus = "2"
  	start = "1"
  	cluster = "clustername"
  	memory_mb = "2048"
  	guest_id = "guest_id"
  	name = "name"
  	size_gb	= 16
  	_delete	= "false"
  	datastore	"Datastore_name"

if you have already built the terraform-foreman source then you are ready to test. Navigate to the directory where you saved your terraform config ( and execute:

terraform plan

This will interrogate the provider and should output something similar to TODO

if you have already planned the terraform resources you can taint them essentially marking them to be rebuilt

# Taint the complex example vm
terraform taint foreman_server.complex_VM

Now you can write your own plan similar to the example. Reference the terraform documentation at

Once a plan has been created you are ready to apply the plan and actually deploy.

Currently I havent implemented the API calls directly to foreman, instead I have utilized foreman's Hammer CLI. I fully intend to replace this at some stage. It is simply a means to an end at this stage. Also only create has been completed, ran out of time this week. Follow the instructions on the Hammer guthub page for installation

# In the directory of your file
terraform apply

This will interrogate the provider and make the changes. If a server isn't built for instance it will call the create method and the provider will instantiate the resource.

How to Build the Source

In order to build/install the source, navigate to the checked out directory and ensure your $GOPATH is defined.


go install


If you'd like to contribute to this codebase please do!

I would be more than pleased if you did but please remember I am not a programmer by default. Go easy on me! lol

Contributing Instructions

# Fork it on GitHub
git clone
cd terraform-provider-foreman
git checkout -b my_awesome_feature_branch master
# Make your awesome changes
git commit -a -m "my awesome changes explained"
# Repeat till your happy
git push origin my_awesome_feature_branch
# Submit a pull request at
# Explain your changes in PR and include test instrcutions.
# I'll hopefully accept it and we'll be on our way to shared awesomeness.