paybyphone / terraform-provider-phpipam

Terraform provider plugin for PHPIPAM (https://phpipam.net/)
Other
13 stars 24 forks source link
phpipam phpipam-api terraform

Terraform Provider Plugin for PHPIPAM

This repository holds a external plugin for a Terraform provider to manage resources within PHPIPAM, an open source IP address management system.

About PHPIPAM

PHPIPAM is an open source IP address management system written in PHP. It has an evolving API that allows for the management and lookup of data that has been entered into the system. Through our Go integration phpipam-sdk-go, we have been able to take this API and integrate it into Terraform, allowing for the management and lookup of sections, VLANs, subnets, and IP addresses, entirely within Terraform.

Installing

See the Plugin Basics page of the Terraform docs to see how to plunk this into your config. Check the releases page of this repo to get releases for Linux, OS X, and Windows.

Usage

After installation, to use the plugin, simply use any of its resources or data sources (such as phpipam_subnet or phpipam_address in a Terraform configuration.

Credentials can be supplied via configuration variables to the phpipam provider instance, or via environment variables. These are documented in the next section.

You can see the following example below for a simple usage example that reserves the first available IP address in a subnet. This address could then be passed along to the configuration for a VM, say, for example, a vsphere_virtual_machine resource.

provider "phpipam" {
  app_id   = "test"
  endpoint = "https://phpipam.example.com/api"
  password = "PHPIPAM_PASSWORD"
  username = "Admin"
}

data "phpipam_subnet" "subnet" {
  subnet_address = "10.10.2.0"
  subnet_mask    = 24
}

data "phpipam_first_free_address" "next_address" {
  subnet_id = "${data.phpipam_subnet.subnet.subnet_id}"
}

resource "phpipam_address" {
  subnet_id   = "${data.phpipam_subnet.subnet.subnet_id}"
  ip_address  = "${data.phpipam_first_free_address.next_address.ip_address}"
  hostname    = "tf-test-host.example.internal"
  description = "Managed by Terraform"

  lifecycle {
    ignore_changes = [
      "subnet_id",
      "ip_address",
    ]
  }
}

Plugin Options

The options for the plugin are as follows:

Data Sources

The following data sources are supplied by this plugin:

The phpipam_address Data Source

The phpipam_address data source allows one to get information about a specific IP address within PHPIPAM. Use this address to get general information about a specific IP address such as its host name, description and more.

Lookups for IP addresses can only happen at this time via its entry in the database, or the IP address itself. Future versions of this resource, when such features become generally available in the PHPIPAM API, will allow lookup based on host name, allowing for better ability for this resource to discover IP addresses that have been pre-assigned for a specific resource.

Example:

data "phpipam_address" "address" {
  ip_address = "10.10.1.1"
}

output "address_description" {
  value = "${data.phpipam_address.address.description}"
}

Example With description:

data "phpipam_address" "address" {
  subnet_id         = 3
  description_match = "Customer 1"
}

output "address_description" {
  value = "${data.phpipam_address.address.description}"
}

Example With custom_field_filter:

data "phpipam_address" "address" {
  subnet_id = 3

  custom_field_filter {
    CustomTestAddresses = ".*terraform.*"
  }
}

output "address_description" {
  value = "${data.phpipam_address.address.description}"
}
Argument Reference

The data source takes the following parameters:

⚠️ NOTE: description, hostname, and custom_field_filter fields return the first match found without any warnings. If you are looking to return multiple addresses, combine this data source with the phpipam_addresses data source.

⚠️ NOTE: An empty or unspecified custom_field_filter value is the equivalent to a regular expression that matches everything, and hence will return the first address it sees in the subnet.

Arguments are processed in the following order of precedence:

Attribute Reference

The following attributes are exported:

The phpipam_addresses Data Source

The phpipam_addresses data source allows you to search for IP addresses, much in the same way as you can in the single-form phpipam_address data source. However, multiple addresses are returned from this data source as a single list of address IDs as they are found in the PHPIPAM database. You can then use the single-form phpipam_address data source to extract the IP data for each matched address in the database.

Example:

⚠️ NOTE: The below example requires Terraform v0.9.0 or later!

data "phpipam_addresses" "address_search" {
  subnet_id = 3

  custom_field_filter {
    CustomTestAddresses = ".*terraform.*"
  }
}

data "phpipam_address" "addresses" {
  count      = "${length(data.phpipam_addresses.address_search.address_ids)}"
  address_id = "${element(data.phpipam_addresses.address_search.address_ids, count.index)}"
}

output "ip_addresses" {
  value = ["${data.phpipam_address.addresses.*.ip_address}"]
}
Argument Reference

The data source takes the following parameters:

One of the following fields is required alongside subnet_id:

⚠️ NOTE: An empty or unspecified custom_field_filter value is the equivalent to a regular expression that matches everything, and hence will return all addresses that contain the referenced custom field key!

Attribute Reference

The following attributes are exported:

The phpipam_first_free_address Data Source

The phpipam_first_free_address data source allows you to get the next available IP address in a specific subnet in PHPIPAM. Using this resource allows you to automatically allocate an IP address that can be used as an IP address in resources such as vsphere_virtual_machine, or other virtual machine-like resources that require static IP addresses.

Note that not having any addresses available will cause the Terraform run to fail. Conversely, marking a subnet as unavailable or used will not prevent this data source from returning an IP address, so be aware of this while using this resource.

Example:

// Look up the subnet
data "phpipam_subnet" "subnet" {
  subnet_address = "10.10.2.0"
  subnet_mask    = 24
}

// Get the first available address
data "phpipam_first_free_address" "next_address" {
  subnet_id = "${data.phpipam_subnet.subnet.subnet_id}"
}

// Reserve the address. Note that we use ignore_changes here to ensure that we
// don't end up re-allocating this address on future Terraform runs.
resource "phpipam_address" {
  subnet_id   = "${data.phpipam_subnet.subnet.subnet_id}"
  ip_address  = "${data.phpipam_first_free_address.next_address.ip_address}"
  hostname    = "tf-test-host.example.internal"
  description = "Managed by Terraform"

  lifecycle {
    ignore_changes = [
      "subnet_id",
      "ip_address",
    ]
  }
}

// Supply the IP address to an instance. Note that we are also ignoring
// network_interface here to ensure the IP address does not get re-calculated.
resource "vsphere_virtual_machine" "web" {
  name   = "terraform-web"
  vcpu   = 2
  memory = 4096

  network_interface {
    label        = "VM Network"
    ipv4_address = "${data.phpipam_first_free_address.next_address.ip_address}"
  }

  disk {
    template = "centos-7"
  }

  ignore_changes = [
    "network_interface",
  ]
}
Argument Reference

The data source takes the following parameters:

Attribute Reference

The following attributes are exported:

The phpipam_section Data Source

The phpipam_section data source allows one to look up a specific section, either by database ID or name. This data can then be used to manage other parts of PHPIPAM, such as in the event that the section name is known but not its ID, which is required for managing subnets.

Example:

data "phpipam_section" "section" {
  name = "Customers"
}

resource "phpipam_subnet" "subnet" {
  section_id = "${data.phpipam_section.section.section_id}"
  subnet_address = "10.10.3.0"
  subnet_mask = 24
}
Argument Reference

The data source takes the following parameters:

One of section_id or name must be supplied. If both are supplied, section_id is used.

Attribute Reference

The following attributes are exported:

The phpipam_subnet Data Source

The phpipam_subnet data source gets information on a subnet such as its ID (required for creating addresses), description, and more.

Example:

// Look up the subnet
data "phpipam_subnet" "subnet" {
  subnet_address = "10.10.2.0"
  subnet_mask    = 24
}

// Reserve the address.
resource "phpipam_address" {
  subnet_id   = "${data.phpipam_subnet.subnet.subnet_id}"
  ip_address  = "10.10.2.10"
  hostname    = "tf-test-host.example.internal"
  description = "Managed by Terraform"
}

Example with description_match:

// Look up the subnet (matching on either case of "customer")
data "phpipam_subnet" "subnet" {
  section_id        = 1
  description_match = "[Cc]ustomer 2"
}

// Get the first available address
data "phpipam_first_free_address" "next_address" {
  subnet_id = "${data.phpipam_subnet.subnet.subnet_id}"
}

// Reserve the address. Note that we use ignore_changes here to ensure that we
// don't end up re-allocating this address on future Terraform runs.
resource "phpipam_address" {
  subnet_id   = "${data.phpipam_subnet.subnet.subnet_id}"
  ip_address  = "${data.phpipam_first_free_address.next_address.ip_address}"
  hostname    = "tf-test-host.example.internal"
  description = "Managed by Terraform"

  lifecycle {
    ignore_changes = [
      "subnet_id",
      "ip_address",
    ]
  }
}

Example With custom_field_filter:

// Look up the subnet
data "phpipam_subnet" "subnet" {
  section_id = 1

  custom_field_filter = {
    CustomTestSubnets = ".*terraform.*"
  }
}

// Get the first available address
data "phpipam_first_free_address" "next_address" {
  subnet_id = "${data.phpipam_subnet.subnet.subnet_id}"
}

// Reserve the address. Note that we use ignore_changes here to ensure that we
// don't end up re-allocating this address on future Terraform runs.
resource "phpipam_address" {
  subnet_id   = "${data.phpipam_subnet.subnet.subnet_id}"
  ip_address  = "${data.phpipam_first_free_address.next_address.ip_address}"
  hostname    = "tf-test-host.example.internal"
  description = "Managed by Terraform"

  lifecycle {
    ignore_changes = [
      "subnet_id",
      "ip_address",
    ]
  }
}
Argument Reference

The data source takes the following parameters:

⚠️ NOTE: Searches with the description, description_match and custom_field_filter fields return the first match found without any warnings. Conversely, the resource fails if it somehow finds multiple results on a CIDR (subnet and mask) search - this is to assert that you are getting the subnet you requested. If you want to return multiple results, combine this data source with the phpipam_subnets data source.

⚠️ NOTE: An empty or unspecified custom_field_filter value is the equivalent to a regular expression that matches everything, and hence will return the first subnetit sees in the section.

Arguments are processed in the following order of precedence:

Attribute Reference

The following attributes are exported:

The phpipam_subnets Data Source

The phpipam_subnets data source allows you to search for subnets, much in the same way as you can in the single-form phpipam_subnet data source. However, multiple subnets are returned from this data source as a single list of subnet IDs as they are found in the PHPIPAM database. You can then use the single-form phpipam_subnet data source to extract the subnet data for each matched network in the database.

Example:

⚠️ NOTE: The below example requires Terraform v0.9.0 or later!

data "phpipam_subnets" "subnet_search" {
  subnet_id = 3

  custom_field_filter {
    CustomTestSubnets = ".*terraform.*"
  }
}

data "phpipam_subnet" "subnets" {
  count     = "${length(data.phpipam_subnets.subnet_search.subnet_ids)}"
  subnet_id = "${element(data.phpipam_subnets.subnet_search.subnet_ids, count.index)}"
}

output "subnet_addresses" {
  value = ["${data.phpipam_subnet.subnets.*.ip_address}"]
}

output "subnet_cidrs" {
  value = ["${formatlist("%s/%d", data.phpipam_subnet.subnets.*.subnet_address, data.phpipam_subnet.subnets.*.subnet_mask)}"]
}
Argument Reference

The data source takes the following parameters:

One of the following below parameters is required:

You can find documentation for the regular expression syntax used with the description_match and custom_field_filter attributes here.

⚠️ NOTE: An empty or unspecified custom_field_filter value is the equivalent to a regular expression that matches everything, and hence will return all subnets that contain the referenced custom field key!

Attribute Reference

The following attributes are exported:

The phpipam_vlan Data Source

The phpipam_vlan data source allows one to look up a VLAN in the PHPIPAM database. This can then be used to assign a VLAN to a subnet in the phpipam_subnet resource. It can also be used to gather other information on the VLAN.

Example:

data "phpipam_section" "section" {
  name = "Customers"
}

data "phpipam_vlan" "vlan" {
  number = 1000
}

resource "phpipam_subnet" "subnet" {
  section_id     = "${data.phpipam_section.section.section_id}"
  subnet_address = "10.10.3.0"
  subnet_mask    = 24
  vlan_id        = "${data.phpipam_vlan.vlan.vlan_id}"
}
Argument Reference

The data source takes the following parameters:

One of vlan_id or number must be supplied. If both are supplied, vlan_id is used.

Attribute Reference

The following attributes are exported:

Resources

The following resources are supplied by this plugin:

The phpipam_address Resource

The phpipam_address resource manages an IP address in PHPIPAM. You can use it to create IP address reservations for IP addresses that have been created by other Terraform resources, or supplied by the phpipam_first_free_address data source. An example usage is below.

⚠️ NOTE: If you are using the phpipam_first_free_address to get the first free IP address in a specific subnet, make sure you set subnet_id and ip_address as ignored attributes with the ignore_changes lifecycle attribute. This will prevent Terraform from perpetually deleting and re-allocating the address when it sees a different available IP address in the phpipam_first_free_address data source.

Example:

// Look up the subnet
data "phpipam_subnet" "subnet" {
  subnet_address = "10.10.2.0"
  subnet_mask    = 24
}

// Get the first available address
data "phpipam_first_free_address" "next_address" {
  subnet_id = "${data.phpipam_subnet.subnet.subnet_id}"
}

// Reserve the address. Note that we use ignore_changes here to ensure that we
// don't end up re-allocating this address on future Terraform runs.
resource "phpipam_address" {
  subnet_id   = "${data.phpipam_subnet.subnet.subnet_id}"
  ip_address  = "${data.phpipam_first_free_address.next_address.ip_address}"
  hostname    = "tf-test-host.example.internal"
  description = "Managed by Terraform"

  custom_fields = {
    CustomTestAddresses = "terraform-test"
  }

  lifecycle {
    ignore_changes = [
      "subnet_id",
      "ip_address",
    ]
  }
}
Argument Reference

The resource takes the following parameters:

⚠️ NOTE on custom fields: PHPIPAM installations with custom fields must have all fields set to optional when using this plugin. For more info see here. Further to this, either ensure that your fields also do not have default values, or ensure the default is set in your TF configuration. Diff loops may happen otherwise!

Attribute Reference

The following attributes are exported:

The phpipam_section Resource

The phpipam_section resource manages a PHPIPAM section - a top-level category that subnets and IP addresses are entered into. Use this resource if you want to manage a section entirely from Terraform. If you just need to get information on a section use the phpipam_section data source instead.

Example:

// Create a section
resource "phpipam_section" "section" {
  name        = "tf-test"
  description = "Terraform test section"
}
Argument Reference

The resource takes the following parameters:

Attribute Reference

The following attributes are exported:

The phpipam_subnet Resource

The phpipam_subnet resource can be used to create and manage a subnet in PHPIPAM. Use it to manage details on subnets you create in Terraform for other things, such as storing the IDs of the subnets you create for AWS, or for a full top-down management of subnets and IP addresses in Terraform. If you just need to get information on a subnet, use the phpipam_subnet data source instead.

Example:

data "phpipam_section" "section" {
  name = "Customers"
}

resource "phpipam_subnet" "subnet" {
  section_id     = "${data.phpipam_section.section.section_id}"
  subnet_address = "10.10.3.0"
  subnet_mask    = 24

  custom_fields = {
    CustomTestSubnets = "terraform-test"
  }
}
Argument Reference

The resource takes the following parameters:

⚠️ NOTE on custom fields: PHPIPAM installations with custom fields must have all fields set to optional when using this plugin. For more info see here. Further to this, either ensure that your fields also do not have default values, or ensure the default is set in your TF configuration. Diff loops may happen otherwise!

Attribute Reference

The following attributes are exported:

The phpipam_vlan Resource

The phpipam_vlan resource can be used to manage a VLAN on PHPIPAM. Use it to set up a VLAN through Terraform, or update details such as its name or description. If you are just looking for information on a VLAN, use the phpipam_vlan data source instead.

Example:

resource "phpipam_vlan" "vlan" {
  name        = "tf-test"
  number      = 1000
  description = "Managed by Terraform"

  custom_fields = {
    CustomTestVLANs = "terraform-test"
  }
}
Argument Reference

The resource takes the following parameters:

⚠️ NOTE on custom fields: PHPIPAM installations with custom fields must have all fields set to optional when using this plugin. For more info see here. Further to this, either ensure that your fields also do not have default values, or ensure the default is set in your TF configuration. Diff loops may happen otherwise!

Attribute Reference

The following attributes are exported:

LICENSE

Copyright 2017 PayByPhone Technologies, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.