Merge branch 'master' into b-data-diff-lag
This commit is contained in:
commit
8b252cfd2b
33
CHANGELOG.md
33
CHANGELOG.md
|
@ -11,46 +11,48 @@ FEATURES:
|
||||||
|
|
||||||
* **New Command:** `terraform state` to provide access to a variety of state manipulation functions [GH-5811]
|
* **New Command:** `terraform state` to provide access to a variety of state manipulation functions [GH-5811]
|
||||||
* **New Provider:** `grafana` [GH-6206]
|
* **New Provider:** `grafana` [GH-6206]
|
||||||
* **New Resource:** `aws_rds_cluster_parameter_group` [GH-5269]
|
* **New Provider:** `random` - allows generation of random values without constantly generating diffs [GH6672]
|
||||||
* **New Resource:** `openstack_blockstorage_volume_v2` [GH-6693]
|
|
||||||
* **New Resource:** `vsphere_virtual_disk` [GH-6273]
|
|
||||||
* **New Resource:** `aws_iam_group_policy_attachment` [GH-6858]
|
* **New Resource:** `aws_iam_group_policy_attachment` [GH-6858]
|
||||||
* **New Resource:** `aws_iam_role_policy_attachment` [GH-6858]
|
* **New Resource:** `aws_iam_role_policy_attachment` [GH-6858]
|
||||||
* **New Resource:** `aws_iam_user_policy_attachment` [GH-6858]
|
* **New Resource:** `aws_iam_user_policy_attachment` [GH-6858]
|
||||||
|
* **New Resource:** `aws_rds_cluster_parameter_group` [GH-5269]
|
||||||
|
* **New Resource:** `openstack_blockstorage_volume_v2` [GH-6693]
|
||||||
|
* **New Resource:** `vsphere_virtual_disk` [GH-6273]
|
||||||
* core: Data Resources are now supported. Values are refreshed, and available during the planning stage [GH-6598]
|
* core: Data Resources are now supported. Values are refreshed, and available during the planning stage [GH-6598]
|
||||||
* core: Lists and maps can now be used as first class types for variables, and may be passed between modules [GH-6322]
|
* core: Lists and maps can now be used as first class types for variables, and may be passed between modules [GH-6322]
|
||||||
* core: The `terraform plan` command no longer persists state. [GH-6811]
|
|
||||||
* core: Tainted resources now show up in the plan and respect dependency ordering [GH-6600]
|
* core: Tainted resources now show up in the plan and respect dependency ordering [GH-6600]
|
||||||
|
* core: The `terraform plan` command no longer persists state. [GH-6811]
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
* core: The `jsonencode` interpolation function now supports encoding lists and maps [GH-6749]
|
* core: The `jsonencode` interpolation function now supports encoding lists and maps [GH-6749]
|
||||||
* provider/aws: Add `option_settings` to `aws_db_option_group` [GH-6560]
|
* provider/aws: Add `option_settings` to `aws_db_option_group` [GH-6560]
|
||||||
|
* provider/aws: Add more explicit support for Skipping Final Snapshot in RDS Cluster [GH-6795]
|
||||||
* provider/aws: Add support for S3 Bucket Acceleration [GH-6628]
|
* provider/aws: Add support for S3 Bucket Acceleration [GH-6628]
|
||||||
* provider/aws: Add support for `kms_key_id` to `aws_db_instance` [GH-6651]
|
* provider/aws: Add support for `kms_key_id` to `aws_db_instance` [GH-6651]
|
||||||
* provider/aws: Support for Redshift Cluster encryption using a KMS key [GH-6712]
|
|
||||||
* provider/aws: Add more explicit support for Skipping Final Snapshot in RDS Cluster [GH-6795]
|
|
||||||
* provider/aws: Set default description to "Managed by Terraform" [GH-6104]
|
|
||||||
* provider/aws: SQS use raw policy string if compact fails [GH-6724]
|
|
||||||
* provider/aws: Support tags for AWS redshift cluster [GH-5356]
|
|
||||||
* provider/aws: Add support to `aws_redshift_cluster` for `iam_roles` [GH-6647]
|
* provider/aws: Add support to `aws_redshift_cluster` for `iam_roles` [GH-6647]
|
||||||
* provider/azurerm: Add support for exporting the `azurerm_storage_account` access keys [GH-6742]
|
* provider/aws: SQS use raw policy string if compact fails [GH-6724]
|
||||||
|
* provider/aws: Set default description to "Managed by Terraform" [GH-6104]
|
||||||
|
* provider/aws: Support for Redshift Cluster encryption using a KMS key [GH-6712]
|
||||||
|
* provider/aws: Support tags for AWS redshift cluster [GH-5356]
|
||||||
* provider/azurerm: Add support for EnableIPForwarding to `azurerm_network_interface` [GH-6807]
|
* provider/azurerm: Add support for EnableIPForwarding to `azurerm_network_interface` [GH-6807]
|
||||||
|
* provider/azurerm: Add support for exporting the `azurerm_storage_account` access keys [GH-6742]
|
||||||
* provider/clc: Add support for hyperscale and bareMetal server types and package installation
|
* provider/clc: Add support for hyperscale and bareMetal server types and package installation
|
||||||
* provider/clc: Fix optional server password [GH-6414]
|
* provider/clc: Fix optional server password [GH-6414]
|
||||||
* provider/cloudstack: Enable swapping of ACLs without having to rebuild the network tier [GH-6741]
|
|
||||||
* provider/cloudstack: Add support for affinity groups to `cloudstack_instance` [GH-6898]
|
* provider/cloudstack: Add support for affinity groups to `cloudstack_instance` [GH-6898]
|
||||||
|
* provider/cloudstack: Enable swapping of ACLs without having to rebuild the network tier [GH-6741]
|
||||||
* provider/datadog: Add support for 'require full window' and 'locked' [GH-6738]
|
* provider/datadog: Add support for 'require full window' and 'locked' [GH-6738]
|
||||||
|
* provider/fastly: Add support for Cache Settings [GH-6781]
|
||||||
* provider/fastly: Add support for Service Request Settings on `fastly_service_v1` resources [GH-6622]
|
* provider/fastly: Add support for Service Request Settings on `fastly_service_v1` resources [GH-6622]
|
||||||
* provider/fastly: Add support for custom VCL configuration [GH-6662]
|
* provider/fastly: Add support for custom VCL configuration [GH-6662]
|
||||||
* provider/fastly: Add support for Cache Settings [GH-6781]
|
|
||||||
* provider/google: Support optional uuid naming for Instance Template [GH-6604]
|
* provider/google: Support optional uuid naming for Instance Template [GH-6604]
|
||||||
* provider/openstack: Increase timeouts for image resize, subnets, and routers [GH-6764]
|
|
||||||
* provider/openstack: Add support for client certificate authentication [GH-6279]
|
* provider/openstack: Add support for client certificate authentication [GH-6279]
|
||||||
* provider/openstack: Enable DHCP By Default [GH-6838]
|
|
||||||
* provider/openstack: Allow Neutron-based Floating IP to target a specific tenant [GH-6454]
|
* provider/openstack: Allow Neutron-based Floating IP to target a specific tenant [GH-6454]
|
||||||
* provider/vsphere: Fix bug with `vsphere_virtual_machine` wait for ip [GH-6377]
|
* provider/openstack: Enable DHCP By Default [GH-6838]
|
||||||
|
* provider/openstack: Implement fixed_ip on Neutron floating ip allocations [GH-6837]
|
||||||
|
* provider/openstack: Increase timeouts for image resize, subnets, and routers [GH-6764]
|
||||||
* provider/vsphere: Add support for `controller_type` to `vsphere_virtual_machine` [GH-6785]
|
* provider/vsphere: Add support for `controller_type` to `vsphere_virtual_machine` [GH-6785]
|
||||||
|
* provider/vsphere: Fix bug with `vsphere_virtual_machine` wait for ip [GH-6377]
|
||||||
* provider/vsphere: Virtual machine update disk [GH-6619]
|
* provider/vsphere: Virtual machine update disk [GH-6619]
|
||||||
|
|
||||||
BUG FIXES:
|
BUG FIXES:
|
||||||
|
@ -74,6 +76,7 @@ BUG FIXES:
|
||||||
* provider/google: Fix a bug causing an error attempting to delete an already-deleted `google_compute_disk` [GH-6689]
|
* provider/google: Fix a bug causing an error attempting to delete an already-deleted `google_compute_disk` [GH-6689]
|
||||||
* provider/openstack: Reassociate Floating IP on network changes [GH-6579]
|
* provider/openstack: Reassociate Floating IP on network changes [GH-6579]
|
||||||
* provider/openstack: Ensure CIDRs Are Lower Case [GH-6864]
|
* provider/openstack: Ensure CIDRs Are Lower Case [GH-6864]
|
||||||
|
* provider/openstack: Rebuild Instances On Network Changes [GH-6844]
|
||||||
* provider/vsphere: `gateway` and `ipv6_gateway` are now read from `vsphere_virtual_machine` resources [GH-6522]
|
* provider/vsphere: `gateway` and `ipv6_gateway` are now read from `vsphere_virtual_machine` resources [GH-6522]
|
||||||
* provider/vsphere: `ipv*_gateway` parameters won't force a new `vsphere_virtual_machine` [GH-6635]
|
* provider/vsphere: `ipv*_gateway` parameters won't force a new `vsphere_virtual_machine` [GH-6635]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/builtin/providers/random"
|
||||||
|
"github.com/hashicorp/terraform/plugin"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
plugin.Serve(&plugin.ServeOpts{
|
||||||
|
ProviderFunc: func() terraform.ResourceProvider {
|
||||||
|
return random.Provider()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package main
|
|
@ -116,10 +116,12 @@ wget http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img
|
||||||
glance image-create --name CirrOS --disk-format qcow2 --container-format bare < cirros-0.3.4-x86_64-disk.img
|
glance image-create --name CirrOS --disk-format qcow2 --container-format bare < cirros-0.3.4-x86_64-disk.img
|
||||||
nova flavor-create m1.tform 99 512 5 1 --ephemeral 10
|
nova flavor-create m1.tform 99 512 5 1 --ephemeral 10
|
||||||
_NETWORK_ID=$(nova net-list | grep private | awk -F\| '{print $2}' | tr -d ' ')
|
_NETWORK_ID=$(nova net-list | grep private | awk -F\| '{print $2}' | tr -d ' ')
|
||||||
|
_EXTGW_ID=$(nova net-list | grep public | awk -F\| '{print $2}' | tr -d ' ')
|
||||||
_IMAGE_ID=$(nova image-list | grep CirrOS | awk -F\| '{print $2}' | tr -d ' ' | head -1)
|
_IMAGE_ID=$(nova image-list | grep CirrOS | awk -F\| '{print $2}' | tr -d ' ' | head -1)
|
||||||
echo export OS_IMAGE_NAME="cirros-0.3.4-x86_64-uec" >> openrc
|
echo export OS_IMAGE_NAME="cirros-0.3.4-x86_64-uec" >> openrc
|
||||||
echo export OS_IMAGE_ID="$_IMAGE_ID" >> openrc
|
echo export OS_IMAGE_ID="$_IMAGE_ID" >> openrc
|
||||||
echo export OS_NETWORK_ID=$_NETWORK_ID >> openrc
|
echo export OS_NETWORK_ID=$_NETWORK_ID >> openrc
|
||||||
|
echo export OS_EXTGW_ID=$_EXTGW_ID >> openrc
|
||||||
echo export OS_POOL_NAME="public" >> openrc
|
echo export OS_POOL_NAME="public" >> openrc
|
||||||
echo export OS_FLAVOR_ID=99 >> openrc
|
echo export OS_FLAVOR_ID=99 >> openrc
|
||||||
source openrc demo
|
source openrc demo
|
||||||
|
|
|
@ -67,4 +67,9 @@ func testAccPreCheck(t *testing.T) {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
t.Fatal("OS_NETWORK_ID must be set for acceptance tests")
|
t.Fatal("OS_NETWORK_ID must be set for acceptance tests")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v = os.Getenv("OS_EXTGW_ID")
|
||||||
|
if v == "" {
|
||||||
|
t.Fatal("OS_EXTGW_ID must be set for acceptance tests")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,26 +114,31 @@ func resourceComputeInstanceV2() *schema.Resource {
|
||||||
"uuid": &schema.Schema{
|
"uuid": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
"name": &schema.Schema{
|
"name": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
"port": &schema.Schema{
|
"port": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
"fixed_ip_v4": &schema.Schema{
|
"fixed_ip_v4": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
"fixed_ip_v6": &schema.Schema{
|
"fixed_ip_v6": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
"floating_ip": &schema.Schema{
|
"floating_ip": &schema.Schema{
|
||||||
|
|
|
@ -557,6 +557,53 @@ func TestAccComputeV2Instance_accessIPv4(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccComputeV2Instance_ChangeFixedIP(t *testing.T) {
|
||||||
|
var instance1_1 servers.Server
|
||||||
|
var instance1_2 servers.Server
|
||||||
|
var testAccComputeV2Instance_ChangeFixedIP_1 = fmt.Sprintf(`
|
||||||
|
resource "openstack_compute_instance_v2" "instance_1" {
|
||||||
|
name = "instance_1"
|
||||||
|
security_groups = ["default"]
|
||||||
|
network {
|
||||||
|
uuid = "%s"
|
||||||
|
fixed_ip_v4 = "10.0.0.24"
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
os.Getenv("OS_NETWORK_ID"))
|
||||||
|
|
||||||
|
var testAccComputeV2Instance_ChangeFixedIP_2 = fmt.Sprintf(`
|
||||||
|
resource "openstack_compute_instance_v2" "instance_1" {
|
||||||
|
name = "instance_1"
|
||||||
|
security_groups = ["default"]
|
||||||
|
network {
|
||||||
|
uuid = "%s"
|
||||||
|
fixed_ip_v4 = "10.0.0.25"
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
os.Getenv("OS_NETWORK_ID"))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeV2InstanceDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeV2Instance_ChangeFixedIP_1,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckComputeV2InstanceExists(t, "openstack_compute_instance_v2.instance_1", &instance1_1),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeV2Instance_ChangeFixedIP_2,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckComputeV2InstanceExists(t, "openstack_compute_instance_v2.instance_1", &instance1_2),
|
||||||
|
testAccCheckComputeV2InstanceInstanceIDsDoNotMatch(&instance1_1, &instance1_2),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckComputeV2InstanceDestroy(s *terraform.State) error {
|
func testAccCheckComputeV2InstanceDestroy(s *terraform.State) error {
|
||||||
config := testAccProvider.Meta().(*Config)
|
config := testAccProvider.Meta().(*Config)
|
||||||
computeClient, err := config.computeV2Client(OS_REGION_NAME)
|
computeClient, err := config.computeV2Client(OS_REGION_NAME)
|
||||||
|
@ -726,6 +773,15 @@ func testAccCheckComputeV2InstanceFloatingIPAttach(
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Floating IP %s was not attached to instance %s", fip.ID, instance.ID)
|
return fmt.Errorf("Floating IP %s was not attached to instance %s", fip.ID, instance.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testAccCheckComputeV2InstanceInstanceIDsDoNotMatch(
|
||||||
|
instance1, instance2 *servers.Server) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if instance1.ID == instance2.ID {
|
||||||
|
return fmt.Errorf("Instance was not recreated.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,11 @@ func resourceNetworkingFloatingIPV2() *schema.Resource {
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
"fixed_ip": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +76,7 @@ func resourceNetworkFloatingIPV2Create(d *schema.ResourceData, meta interface{})
|
||||||
FloatingNetworkID: poolID,
|
FloatingNetworkID: poolID,
|
||||||
PortID: d.Get("port_id").(string),
|
PortID: d.Get("port_id").(string),
|
||||||
TenantID: d.Get("tenant_id").(string),
|
TenantID: d.Get("tenant_id").(string),
|
||||||
|
FixedIP: d.Get("fixed_ip").(string),
|
||||||
}
|
}
|
||||||
log.Printf("[DEBUG] Create Options: %#v", createOpts)
|
log.Printf("[DEBUG] Create Options: %#v", createOpts)
|
||||||
floatingIP, err := floatingips.Create(networkingClient, createOpts).Extract()
|
floatingIP, err := floatingips.Create(networkingClient, createOpts).Extract()
|
||||||
|
@ -109,6 +115,7 @@ func resourceNetworkFloatingIPV2Read(d *schema.ResourceData, meta interface{}) e
|
||||||
|
|
||||||
d.Set("address", floatingIP.FloatingIP)
|
d.Set("address", floatingIP.FloatingIP)
|
||||||
d.Set("port_id", floatingIP.PortID)
|
d.Set("port_id", floatingIP.PortID)
|
||||||
|
d.Set("fixed_ip", floatingIP.FixedIP)
|
||||||
poolName, err := getNetworkName(d, meta, floatingIP.FloatingNetworkID)
|
poolName, err := getNetworkName(d, meta, floatingIP.FloatingNetworkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error retrieving floating IP pool name: %s", err)
|
return fmt.Errorf("Error retrieving floating IP pool name: %s", err)
|
||||||
|
|
|
@ -65,6 +65,67 @@ func TestAccNetworkingV2FloatingIP_attach(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccNetworkingV2FloatingIP_fixedip_bind(t *testing.T) {
|
||||||
|
var fip floatingips.FloatingIP
|
||||||
|
var testAccNetworkingV2FloatingIP_fixedip_bind = fmt.Sprintf(`
|
||||||
|
resource "openstack_networking_network_v2" "network_1" {
|
||||||
|
name = "network_1"
|
||||||
|
admin_state_up = "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "openstack_networking_subnet_v2" "subnet_1" {
|
||||||
|
name = "subnet_1"
|
||||||
|
network_id = "${openstack_networking_network_v2.network_1.id}"
|
||||||
|
cidr = "192.168.199.0/24"
|
||||||
|
ip_version = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "openstack_networking_router_interface_v2" "router_interface_1" {
|
||||||
|
router_id = "${openstack_networking_router_v2.router_1.id}"
|
||||||
|
subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "openstack_networking_router_v2" "router_1" {
|
||||||
|
name = "router_1"
|
||||||
|
external_gateway = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "openstack_networking_port_v2" "port_1" {
|
||||||
|
network_id = "${openstack_networking_subnet_v2.subnet_1.network_id}"
|
||||||
|
admin_state_up = "true"
|
||||||
|
fixed_ip {
|
||||||
|
subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}"
|
||||||
|
ip_address = "192.168.199.10"
|
||||||
|
}
|
||||||
|
fixed_ip {
|
||||||
|
subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}"
|
||||||
|
ip_address = "192.168.199.20"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "openstack_networking_floatingip_v2" "ip_1" {
|
||||||
|
pool = "%s"
|
||||||
|
port_id = "${openstack_networking_port_v2.port_1.id}"
|
||||||
|
fixed_ip = "${openstack_networking_port_v2.port_1.fixed_ip.1.ip_address}"
|
||||||
|
}`,
|
||||||
|
os.Getenv("OS_EXTGW_ID"), os.Getenv("OS_POOL_NAME"))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckNetworkingV2FloatingIPDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccNetworkingV2FloatingIP_fixedip_bind,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckNetworkingV2FloatingIPExists(t, "openstack_networking_floatingip_v2.ip_1", &fip),
|
||||||
|
testAccCheckNetworkingV2FloatingIPBoundToCorrectIP(t, &fip, "192.168.199.20"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckNetworkingV2FloatingIPDestroy(s *terraform.State) error {
|
func testAccCheckNetworkingV2FloatingIPDestroy(s *terraform.State) error {
|
||||||
config := testAccProvider.Meta().(*Config)
|
config := testAccProvider.Meta().(*Config)
|
||||||
networkClient, err := config.networkingV2Client(OS_REGION_NAME)
|
networkClient, err := config.networkingV2Client(OS_REGION_NAME)
|
||||||
|
@ -118,6 +179,16 @@ func testAccCheckNetworkingV2FloatingIPExists(t *testing.T, n string, kp *floati
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAccCheckNetworkingV2FloatingIPBoundToCorrectIP(t *testing.T, fip *floatingips.FloatingIP, fixed_ip string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if fip.FixedIP != fixed_ip {
|
||||||
|
return fmt.Errorf("Floating ip associated with wrong fixed ip")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckNetworkingV2InstanceFloatingIPAttach(
|
func testAccCheckNetworkingV2InstanceFloatingIPAttach(
|
||||||
instance *servers.Server, fip *floatingips.FloatingIP) resource.TestCheckFunc {
|
instance *servers.Server, fip *floatingips.FloatingIP) resource.TestCheckFunc {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider returns a terraform.ResourceProvider.
|
||||||
|
func Provider() terraform.ResourceProvider {
|
||||||
|
return &schema.Provider{
|
||||||
|
Schema: map[string]*schema.Schema{},
|
||||||
|
|
||||||
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
|
"random_id": resourceId(),
|
||||||
|
"random_shuffle": resourceShuffle(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stubRead is a do-nothing Read implementation used for our resources,
|
||||||
|
// which don't actually need to do anything on read.
|
||||||
|
func stubRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// stubDelete is a do-nothing Dete implementation used for our resources,
|
||||||
|
// which don't actually need to do anything unusual on delete.
|
||||||
|
func stubDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testAccProviders map[string]terraform.ResourceProvider
|
||||||
|
var testAccProvider *schema.Provider
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testAccProvider = Provider().(*schema.Provider)
|
||||||
|
testAccProviders = map[string]terraform.ResourceProvider{
|
||||||
|
"random": testAccProvider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider(t *testing.T) {
|
||||||
|
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_impl(t *testing.T) {
|
||||||
|
var _ terraform.ResourceProvider = Provider()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccPreCheck(t *testing.T) {
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceId() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: CreateID,
|
||||||
|
Read: stubRead,
|
||||||
|
Delete: stubDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"keepers": &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"byte_length": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"b64": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"hex": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"dec": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateID(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
byteLength := d.Get("byte_length").(int)
|
||||||
|
bytes := make([]byte, byteLength)
|
||||||
|
|
||||||
|
n, err := rand.Reader.Read(bytes)
|
||||||
|
if n != byteLength {
|
||||||
|
return fmt.Errorf("generated insufficient random bytes")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error generating random bytes: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b64Str := base64.RawURLEncoding.EncodeToString(bytes)
|
||||||
|
hexStr := hex.EncodeToString(bytes)
|
||||||
|
|
||||||
|
int := big.Int{}
|
||||||
|
int.SetBytes(bytes)
|
||||||
|
decStr := int.String()
|
||||||
|
|
||||||
|
d.SetId(b64Str)
|
||||||
|
d.Set("b64", b64Str)
|
||||||
|
d.Set("hex", hexStr)
|
||||||
|
d.Set("dec", decStr)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccResourceID(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccResourceIDConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccResourceIDCheck("random_id.foo"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccResourceIDCheck(id string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[id]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", id)
|
||||||
|
}
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
b64Str := rs.Primary.Attributes["b64"]
|
||||||
|
hexStr := rs.Primary.Attributes["hex"]
|
||||||
|
decStr := rs.Primary.Attributes["dec"]
|
||||||
|
|
||||||
|
if got, want := len(b64Str), 6; got != want {
|
||||||
|
return fmt.Errorf("base64 string length is %d; want %d", got, want)
|
||||||
|
}
|
||||||
|
if got, want := len(hexStr), 8; got != want {
|
||||||
|
return fmt.Errorf("hex string length is %d; want %d", got, want)
|
||||||
|
}
|
||||||
|
if len(decStr) < 1 {
|
||||||
|
return fmt.Errorf("decimal string is empty; want at least one digit")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccResourceIDConfig = `
|
||||||
|
resource "random_id" "foo" {
|
||||||
|
byte_length = 4
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,82 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceShuffle() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: CreateShuffle,
|
||||||
|
Read: stubRead,
|
||||||
|
Delete: stubDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"keepers": &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"seed": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"input": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"result": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"result_count": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateShuffle(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
input := d.Get("input").([]interface{})
|
||||||
|
seed := d.Get("seed").(string)
|
||||||
|
|
||||||
|
resultCount := d.Get("result_count").(int)
|
||||||
|
if resultCount == 0 {
|
||||||
|
resultCount = len(input)
|
||||||
|
}
|
||||||
|
result := make([]interface{}, 0, resultCount)
|
||||||
|
|
||||||
|
rand := NewRand(seed)
|
||||||
|
|
||||||
|
// Keep producing permutations until we fill our result
|
||||||
|
Batches:
|
||||||
|
for {
|
||||||
|
perm := rand.Perm(len(input))
|
||||||
|
|
||||||
|
for _, i := range perm {
|
||||||
|
result = append(result, input[i])
|
||||||
|
|
||||||
|
if len(result) >= resultCount {
|
||||||
|
break Batches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("-")
|
||||||
|
d.Set("result", result)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccResourceShuffle(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccResourceShuffleConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
// These results are current as of Go 1.6. The Go
|
||||||
|
// "rand" package does not guarantee that the random
|
||||||
|
// number generator will generate the same results
|
||||||
|
// forever, but the maintainers endeavor not to change
|
||||||
|
// it gratuitously.
|
||||||
|
// These tests allow us to detect such changes and
|
||||||
|
// document them when they arise, but the docs for this
|
||||||
|
// resource specifically warn that results are not
|
||||||
|
// guaranteed consistent across Terraform releases.
|
||||||
|
testAccResourceShuffleCheck(
|
||||||
|
"random_shuffle.default_length",
|
||||||
|
[]string{"a", "c", "b", "e", "d"},
|
||||||
|
),
|
||||||
|
testAccResourceShuffleCheck(
|
||||||
|
"random_shuffle.shorter_length",
|
||||||
|
[]string{"a", "c", "b"},
|
||||||
|
),
|
||||||
|
testAccResourceShuffleCheck(
|
||||||
|
"random_shuffle.longer_length",
|
||||||
|
[]string{"a", "c", "b", "e", "d", "a", "e", "d", "c", "b", "a", "b"},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccResourceShuffleCheck(id string, wants []string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[id]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", id)
|
||||||
|
}
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs := rs.Primary.Attributes
|
||||||
|
|
||||||
|
gotLen := attrs["result.#"]
|
||||||
|
wantLen := strconv.Itoa(len(wants))
|
||||||
|
if gotLen != wantLen {
|
||||||
|
return fmt.Errorf("got %s result items; want %s", gotLen, wantLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, want := range wants {
|
||||||
|
key := fmt.Sprintf("result.%d", i)
|
||||||
|
if got := attrs[key]; got != want {
|
||||||
|
return fmt.Errorf("index %d is %q; want %q", i, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccResourceShuffleConfig = `
|
||||||
|
resource "random_shuffle" "default_length" {
|
||||||
|
input = ["a", "b", "c", "d", "e"]
|
||||||
|
seed = "-"
|
||||||
|
}
|
||||||
|
resource "random_shuffle" "shorter_length" {
|
||||||
|
input = ["a", "b", "c", "d", "e"]
|
||||||
|
seed = "-"
|
||||||
|
result_count = 3
|
||||||
|
}
|
||||||
|
resource "random_shuffle" "longer_length" {
|
||||||
|
input = ["a", "b", "c", "d", "e"]
|
||||||
|
seed = "-"
|
||||||
|
result_count = 12
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,24 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hash/crc64"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewRand returns a seeded random number generator, using a seed derived
|
||||||
|
// from the provided string.
|
||||||
|
//
|
||||||
|
// If the seed string is empty, the current time is used as a seed.
|
||||||
|
func NewRand(seed string) *rand.Rand {
|
||||||
|
var seedInt int64
|
||||||
|
if seed != "" {
|
||||||
|
crcTable := crc64.MakeTable(crc64.ISO)
|
||||||
|
seedInt = int64(crc64.Checksum([]byte(seed), crcTable))
|
||||||
|
} else {
|
||||||
|
seedInt = time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
randSource := rand.NewSource(seedInt)
|
||||||
|
return rand.New(randSource)
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ import (
|
||||||
packetprovider "github.com/hashicorp/terraform/builtin/providers/packet"
|
packetprovider "github.com/hashicorp/terraform/builtin/providers/packet"
|
||||||
postgresqlprovider "github.com/hashicorp/terraform/builtin/providers/postgresql"
|
postgresqlprovider "github.com/hashicorp/terraform/builtin/providers/postgresql"
|
||||||
powerdnsprovider "github.com/hashicorp/terraform/builtin/providers/powerdns"
|
powerdnsprovider "github.com/hashicorp/terraform/builtin/providers/powerdns"
|
||||||
|
randomprovider "github.com/hashicorp/terraform/builtin/providers/random"
|
||||||
rundeckprovider "github.com/hashicorp/terraform/builtin/providers/rundeck"
|
rundeckprovider "github.com/hashicorp/terraform/builtin/providers/rundeck"
|
||||||
softlayerprovider "github.com/hashicorp/terraform/builtin/providers/softlayer"
|
softlayerprovider "github.com/hashicorp/terraform/builtin/providers/softlayer"
|
||||||
statuscakeprovider "github.com/hashicorp/terraform/builtin/providers/statuscake"
|
statuscakeprovider "github.com/hashicorp/terraform/builtin/providers/statuscake"
|
||||||
|
@ -87,6 +88,7 @@ var InternalProviders = map[string]plugin.ProviderFunc{
|
||||||
"packet": packetprovider.Provider,
|
"packet": packetprovider.Provider,
|
||||||
"postgresql": postgresqlprovider.Provider,
|
"postgresql": postgresqlprovider.Provider,
|
||||||
"powerdns": powerdnsprovider.Provider,
|
"powerdns": powerdnsprovider.Provider,
|
||||||
|
"random": randomprovider.Provider,
|
||||||
"rundeck": rundeckprovider.Provider,
|
"rundeck": rundeckprovider.Provider,
|
||||||
"softlayer": softlayerprovider.Provider,
|
"softlayer": softlayerprovider.Provider,
|
||||||
"statuscake": statuscakeprovider.Provider,
|
"statuscake": statuscakeprovider.Provider,
|
||||||
|
|
|
@ -897,7 +897,23 @@ func (n *graphNodeExpandedResourceDestroy) EvalTree() EvalNode {
|
||||||
&EvalRequireState{
|
&EvalRequireState{
|
||||||
State: &state,
|
State: &state,
|
||||||
},
|
},
|
||||||
&EvalApply{
|
// Make sure we handle data sources properly.
|
||||||
|
&EvalIf{
|
||||||
|
If: func(ctx EvalContext) (bool, error) {
|
||||||
|
if n.Resource.Mode == config.DataResourceMode {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
},
|
||||||
|
|
||||||
|
Then: &EvalReadDataApply{
|
||||||
|
Info: info,
|
||||||
|
Diff: &diffApply,
|
||||||
|
Provider: &provider,
|
||||||
|
Output: &state,
|
||||||
|
},
|
||||||
|
Else: &EvalApply{
|
||||||
Info: info,
|
Info: info,
|
||||||
State: &state,
|
State: &state,
|
||||||
Diff: &diffApply,
|
Diff: &diffApply,
|
||||||
|
@ -905,6 +921,7 @@ func (n *graphNodeExpandedResourceDestroy) EvalTree() EvalNode {
|
||||||
Output: &state,
|
Output: &state,
|
||||||
Error: &err,
|
Error: &err,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
&EvalWriteState{
|
&EvalWriteState{
|
||||||
Name: n.stateId(),
|
Name: n.stateId(),
|
||||||
ResourceType: n.Resource.Type,
|
ResourceType: n.Resource.Type,
|
||||||
|
|
|
@ -36,6 +36,7 @@ body.layout-openstack,
|
||||||
body.layout-packet,
|
body.layout-packet,
|
||||||
body.layout-postgresql,
|
body.layout-postgresql,
|
||||||
body.layout-powerdns,
|
body.layout-powerdns,
|
||||||
|
body.layout-random,
|
||||||
body.layout-rundeck,
|
body.layout-rundeck,
|
||||||
body.layout-statuscake,
|
body.layout-statuscake,
|
||||||
body.layout-softlayer,
|
body.layout-softlayer,
|
||||||
|
|
|
@ -267,16 +267,19 @@ The following arguments are supported:
|
||||||
The `network` block supports:
|
The `network` block supports:
|
||||||
|
|
||||||
* `uuid` - (Required unless `port` or `name` is provided) The network UUID to
|
* `uuid` - (Required unless `port` or `name` is provided) The network UUID to
|
||||||
attach to the server.
|
attach to the server. Changing this creates a new server.
|
||||||
|
|
||||||
* `name` - (Required unless `uuid` or `port` is provided) The human-readable
|
* `name` - (Required unless `uuid` or `port` is provided) The human-readable
|
||||||
name of the network.
|
name of the network. Changing this creates a new server.
|
||||||
|
|
||||||
* `port` - (Required unless `uuid` or `name` is provided) The port UUID of a
|
* `port` - (Required unless `uuid` or `name` is provided) The port UUID of a
|
||||||
network to attach to the server.
|
network to attach to the server. Changing this creates a new server.
|
||||||
|
|
||||||
* `fixed_ip_v4` - (Optional) Specifies a fixed IPv4 address to be used on this
|
* `fixed_ip_v4` - (Optional) Specifies a fixed IPv4 address to be used on this
|
||||||
network.
|
network. Changing this creates a new server.
|
||||||
|
|
||||||
|
* `fixed_ip_v6` - (Optional) Specifies a fixed IPv6 address to be used on this
|
||||||
|
network. Changing this creates a new server.
|
||||||
|
|
||||||
* `floating_ip` - (Optional) Specifies a floating IP address to be associated
|
* `floating_ip` - (Optional) Specifies a floating IP address to be associated
|
||||||
with this network. Cannot be combined with a top-level floating IP. See
|
with this network. Cannot be combined with a top-level floating IP. See
|
||||||
|
@ -301,6 +304,9 @@ The `block_device` block supports:
|
||||||
* `destination_type` - (Optional) The type that gets created. Possible values
|
* `destination_type` - (Optional) The type that gets created. Possible values
|
||||||
are "volume" and "local".
|
are "volume" and "local".
|
||||||
|
|
||||||
|
* `delete_on_termination` - (Optional) Delete the volume / block device upon
|
||||||
|
termination of the instance. Defaults to false.
|
||||||
|
|
||||||
The `volume` block supports:
|
The `volume` block supports:
|
||||||
|
|
||||||
* `volume_id` - (Required) The UUID of the volume to attach.
|
* `volume_id` - (Required) The UUID of the volume to attach.
|
||||||
|
|
|
@ -43,6 +43,9 @@ The following arguments are supported:
|
||||||
belongs to the same tenant. Changing this creates a new floating IP (which
|
belongs to the same tenant. Changing this creates a new floating IP (which
|
||||||
may or may not have a different address)
|
may or may not have a different address)
|
||||||
|
|
||||||
|
* `fixed_ip` - Fixed IP of the port to associate with this floating IP. Required if
|
||||||
|
the port has multiple fixed IPs.
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
The following attributes are exported:
|
The following attributes are exported:
|
||||||
|
@ -52,3 +55,4 @@ The following attributes are exported:
|
||||||
* `address` - The actual floating IP address itself.
|
* `address` - The actual floating IP address itself.
|
||||||
* `port_id` - ID of associated port.
|
* `port_id` - ID of associated port.
|
||||||
* `tenant_id` - the ID of the tenant in which to create the floating IP.
|
* `tenant_id` - the ID of the tenant in which to create the floating IP.
|
||||||
|
* `fixed_ip` - The fixed IP which the floating IP maps to.
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
---
|
||||||
|
layout: "random"
|
||||||
|
page_title: "Provider: Random"
|
||||||
|
sidebar_current: "docs-random-index"
|
||||||
|
description: |-
|
||||||
|
The Random provider is used to generate randomness.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Random Provider
|
||||||
|
|
||||||
|
The "random" provider allows the use of randomness within Terraform
|
||||||
|
configurations. This is a *logical provider*, which means that it works
|
||||||
|
entirely within Terraform's logic, and doesn't interact with any other
|
||||||
|
services.
|
||||||
|
|
||||||
|
Unconstrained randomness within a Terraform configuration would not be very
|
||||||
|
useful, since Terraform's goal is to converge on a fixed configuration by
|
||||||
|
applying a diff. Because of this, the "random" provider provides an idea of
|
||||||
|
*managed randomness*: it provides resources that generate random values during
|
||||||
|
their creation and then hold those values steady until the inputs are changed.
|
||||||
|
|
||||||
|
Even with these resources, it is advisable to keep the use of randomness within
|
||||||
|
Terraform configuration to a minimum, and retain it for special cases only;
|
||||||
|
Terraform works best when the configuration is well-defined, since its behavior
|
||||||
|
can then be more readily predicted.
|
||||||
|
|
||||||
|
Unless otherwise stated within the documentation of a specific resource, this
|
||||||
|
provider's results are **not** sufficiently random for cryptographic use.
|
||||||
|
|
||||||
|
For more information on the specific resources available, see the links in the
|
||||||
|
navigation bar. Read on for information on the general patterns that apply
|
||||||
|
to this provider's resources.
|
||||||
|
|
||||||
|
## Resource "Keepers"
|
||||||
|
|
||||||
|
As noted above, the random resources generate randomness only when they are
|
||||||
|
created; the results produced are stored in the Terraform state and re-used
|
||||||
|
until the inputs change, prompting the resource to be recreated.
|
||||||
|
|
||||||
|
The resources all provide a map argument called `keepers` that can be populated
|
||||||
|
with arbitrary key/value pairs that should be selected such that they remain
|
||||||
|
the same until new random values are desired.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "random_id" "server" {
|
||||||
|
keepers = {
|
||||||
|
# Generate a new id each time we switch to a new AMI id
|
||||||
|
ami_id = "${var.ami_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_length = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "server" {
|
||||||
|
tags = {
|
||||||
|
Name = "web-server ${random_id.server.hex}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the AMI id "through" the random_id resource to ensure that
|
||||||
|
# both will change together.
|
||||||
|
ami = "${random_id.server.keepers.ami_id}"
|
||||||
|
|
||||||
|
# ... (other aws_instance arguments) ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Resource "keepers" are optional. The other arguments to each resource must
|
||||||
|
*also* remain constant in order to retain a random result.
|
||||||
|
|
||||||
|
To force a random result to be replaced, the `taint` command can be used to
|
||||||
|
produce a new result on the next run.
|
|
@ -0,0 +1,69 @@
|
||||||
|
---
|
||||||
|
layout: "random"
|
||||||
|
page_title: "Random: random_id"
|
||||||
|
sidebar_current: "docs-random-resource-id"
|
||||||
|
description: |-
|
||||||
|
Generates a random identifier.
|
||||||
|
---
|
||||||
|
|
||||||
|
# random\_id
|
||||||
|
|
||||||
|
The resource `random_id` generates random numbers that are intended to be
|
||||||
|
used as unique identifiers for other resources.
|
||||||
|
|
||||||
|
Unlike other resources in the "random" provider, this resource *does* use a
|
||||||
|
cryptographic random number generator in order to minimize the chance of
|
||||||
|
collisions, making the results of this resource when a 32-byte identifier
|
||||||
|
is requested of equivalent uniqueness to a type-4 UUID.
|
||||||
|
|
||||||
|
This resource can be used in conjunction with resources that have,
|
||||||
|
the `create_before_destroy` lifecycle flag set, to avoid conflicts with
|
||||||
|
unique names during the brief period where both the old and new resources
|
||||||
|
exist concurrently.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
The following example shows how to generate a unique name for an AWS EC2
|
||||||
|
instance that changes each time a new AMI id is selected.
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "random_id" "server" {
|
||||||
|
keepers = {
|
||||||
|
# Generate a new id each time we switch to a new AMI id
|
||||||
|
ami_id = "${var.ami_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_length = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "server" {
|
||||||
|
tags = {
|
||||||
|
Name = "web-server ${random_id.server.hex}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the AMI id "through" the random_id resource to ensure that
|
||||||
|
# both will change together.
|
||||||
|
ami = "${random_id.server.keepers.ami_id}"
|
||||||
|
|
||||||
|
# ... (other aws_instance arguments) ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `byte_length` - (Required) The number of random bytes to produce. The
|
||||||
|
minimum value is 1, which produces eight bits of randomness.
|
||||||
|
|
||||||
|
* `keepers` - (Optional) Arbitrary map of values that, when changed, will
|
||||||
|
trigger a new id to be generated. See
|
||||||
|
[the main provider documentation](../index.html) for more information.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `b64` - The generated id presented in base64, using the URL-friendly character set: case-sensitive letters, digits and the characters `_` and `-`.
|
||||||
|
* `hex` - The generated id presented in padded hexadecimal digits. This result will always be twice as long as the requested byte length.
|
||||||
|
* `decimal` - The generated id presented in non-padded decimal digits.
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
layout: "random"
|
||||||
|
page_title: "Random: random_shuffle"
|
||||||
|
sidebar_current: "docs-random-resource-shuffle"
|
||||||
|
description: |-
|
||||||
|
Produces a random permutation of a given list.
|
||||||
|
---
|
||||||
|
|
||||||
|
# random\_shuffle
|
||||||
|
|
||||||
|
The resource `random_shuffle` generates a random permutation of a list
|
||||||
|
of strings given as an argument.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "random_shuffle" "az" {
|
||||||
|
input = ["us-west-1a", "us-west-1c", "us-west-1d", "us-west-1e"]
|
||||||
|
result_count = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_elb" "example" {
|
||||||
|
# Place the ELB in any two of the given availability zones, selected
|
||||||
|
# at random.
|
||||||
|
availability_zones = ["${random_shuffle.az.result}"]
|
||||||
|
|
||||||
|
# ... and other aws_elb arguments ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `input` - (Required) The list of strings to shuffle.
|
||||||
|
|
||||||
|
* `result_count` - (Optional) The number of results to return. Defaults to
|
||||||
|
the number of items in the `input` list. If fewer items are requested,
|
||||||
|
some elements will be excluded from the result. If more items are requested,
|
||||||
|
items will be repeated in the result but not more frequently than the number
|
||||||
|
of items in the input list.
|
||||||
|
|
||||||
|
* `keepers` - (Optional) Arbitrary map of values that, when changed, will
|
||||||
|
trigger a new id to be generated. See
|
||||||
|
[the main provider documentation](../index.html) for more information.
|
||||||
|
|
||||||
|
* `seed` - (Optional) Arbitrary string with which to seed the random number
|
||||||
|
generator, in order to produce less-volatile permutations of the list.
|
||||||
|
**Important:** Even with an identical seed, it is not guaranteed that the
|
||||||
|
same permutation will be produced across different versions of Terraform.
|
||||||
|
This argument causes the result to be *less volatile*, but not fixed for
|
||||||
|
all time.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `result` - Random permutation of the list of strings given in `input`.
|
||||||
|
|
|
@ -276,6 +276,10 @@
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-providers-powerdns") %>>
|
<li<%= sidebar_current("docs-providers-powerdns") %>>
|
||||||
<a href="/docs/providers/powerdns/index.html">PowerDNS</a>
|
<a href="/docs/providers/powerdns/index.html">PowerDNS</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-providers-random") %>>
|
||||||
|
<a href="/docs/providers/random/index.html">Random</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-providers-rundeck") %>>
|
<li<%= sidebar_current("docs-providers-rundeck") %>>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<% wrap_layout :inner do %>
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<div class="docs-sidebar hidden-print affix-top" role="complementary">
|
||||||
|
<ul class="nav docs-sidenav">
|
||||||
|
<li<%= sidebar_current("docs-home") %>>
|
||||||
|
<a href="/docs/providers/index.html">« Documentation Home</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-random-index") %>>
|
||||||
|
<a href="/docs/providers/random/index.html">Random Provider</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current(/^docs-random-resource/) %>>
|
||||||
|
<a href="#">Resources</a>
|
||||||
|
<ul class="nav nav-visible">
|
||||||
|
<li<%= sidebar_current("docs-random-resource-id") %>>
|
||||||
|
<a href="/docs/providers/random/r/id.html">random_id</a>
|
||||||
|
</li>
|
||||||
|
<li<%= sidebar_current("docs-random-resource-shuffle") %>>
|
||||||
|
<a href="/docs/providers/random/r/shuffle.html">random_shuffle</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= yield %>
|
||||||
|
<% end %>
|
Loading…
Reference in New Issue