Merge branch 'docker_network' of https://github.com/ColinHebert/terraform into ColinHebert-docker_network
This commit is contained in:
commit
ee7553f076
|
@ -28,6 +28,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
ResourcesMap: map[string]*schema.Resource{
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
"docker_container": resourceDockerContainer(),
|
"docker_container": resourceDockerContainer(),
|
||||||
"docker_image": resourceDockerImage(),
|
"docker_image": resourceDockerImage(),
|
||||||
|
"docker_network": resourceDockerNetwork(),
|
||||||
},
|
},
|
||||||
|
|
||||||
ConfigureFunc: providerConfigure,
|
ConfigureFunc: providerConfigure,
|
||||||
|
|
|
@ -244,6 +244,14 @@ func resourceDockerContainer() *schema.Resource {
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"networks": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
Set: stringSetHash,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,14 @@ func resourceDockerContainerCreate(d *schema.ResourceData, meta interface{}) err
|
||||||
|
|
||||||
d.SetId(retContainer.ID)
|
d.SetId(retContainer.ID)
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("networks"); ok {
|
||||||
|
connectionOpts := dc.NetworkConnectionOptions{Container: retContainer.ID}
|
||||||
|
|
||||||
|
for _, network := range v.(*schema.Set).List() {
|
||||||
|
client.ConnectNetwork(network.(string), connectionOpts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
creationTime = time.Now()
|
creationTime = time.Now()
|
||||||
if err := client.StartContainer(retContainer.ID, hostConfig); err != nil {
|
if err := client.StartContainer(retContainer.ID, hostConfig); err != nil {
|
||||||
return fmt.Errorf("Unable to start container: %s", err)
|
return fmt.Errorf("Unable to start container: %s", err)
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceDockerNetwork() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceDockerNetworkCreate,
|
||||||
|
Read: resourceDockerNetworkRead,
|
||||||
|
Delete: resourceDockerNetworkDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"check_duplicate": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"driver": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"options": &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ipam_driver": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ipam_config": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: getIpamConfigElem(),
|
||||||
|
Set: resourceDockerIpamConfigHash,
|
||||||
|
},
|
||||||
|
|
||||||
|
"id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"scope": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIpamConfigElem() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"subnet": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ip_range": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"gateway": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"aux_address": &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDockerIpamConfigHash(v interface{}) int {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
|
||||||
|
if v, ok := m["subnet"]; ok {
|
||||||
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := m["ip_range"]; ok {
|
||||||
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := m["gateway"]; ok {
|
||||||
|
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := m["aux_address"]; ok {
|
||||||
|
auxAddress := v.(map[string]interface{})
|
||||||
|
|
||||||
|
keys := make([]string, len(auxAddress))
|
||||||
|
i := 0
|
||||||
|
for k, _ := range auxAddress {
|
||||||
|
keys[i] = k
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
for _, k := range keys {
|
||||||
|
buf.WriteString(fmt.Sprintf("%v-%v-", k, auxAddress[k].(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashcode.String(buf.String())
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
dc "github.com/fsouza/go-dockerclient"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceDockerNetworkCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*dc.Client)
|
||||||
|
|
||||||
|
createOpts := dc.CreateNetworkOptions{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("check_duplicate"); ok {
|
||||||
|
createOpts.CheckDuplicate = v.(bool)
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("driver"); ok {
|
||||||
|
createOpts.Driver = v.(string)
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("options"); ok {
|
||||||
|
createOpts.Options = v.(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
ipamOpts := dc.IPAMOptions{}
|
||||||
|
ipamOptsSet := false
|
||||||
|
if v, ok := d.GetOk("ipam_driver"); ok {
|
||||||
|
ipamOpts.Driver = v.(string)
|
||||||
|
ipamOptsSet = true
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk("ipam_config"); ok {
|
||||||
|
ipamOpts.Config = ipamConfigSetToIpamConfigs(v.(*schema.Set))
|
||||||
|
ipamOptsSet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipamOptsSet {
|
||||||
|
createOpts.IPAM = ipamOpts
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var retNetwork *dc.Network
|
||||||
|
if retNetwork, err = client.CreateNetwork(createOpts); err != nil {
|
||||||
|
return fmt.Errorf("Unable to create network: %s", err)
|
||||||
|
}
|
||||||
|
if retNetwork == nil {
|
||||||
|
return fmt.Errorf("Returned network is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(retNetwork.ID)
|
||||||
|
d.Set("name", retNetwork.Name)
|
||||||
|
d.Set("scope", retNetwork.Scope)
|
||||||
|
d.Set("driver", retNetwork.Driver)
|
||||||
|
d.Set("options", retNetwork.Options)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDockerNetworkRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*dc.Client)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var retNetwork *dc.Network
|
||||||
|
if retNetwork, err = client.NetworkInfo(d.Id()); err != nil {
|
||||||
|
if _, ok := err.(*dc.NoSuchNetwork); !ok {
|
||||||
|
return fmt.Errorf("Unable to inspect network: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if retNetwork == nil {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("scope", retNetwork.Scope)
|
||||||
|
d.Set("driver", retNetwork.Driver)
|
||||||
|
d.Set("options", retNetwork.Options)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDockerNetworkDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*dc.Client)
|
||||||
|
|
||||||
|
if err := client.RemoveNetwork(d.Id()); err != nil {
|
||||||
|
if _, ok := err.(*dc.NoSuchNetwork); !ok {
|
||||||
|
return fmt.Errorf("Error deleting network %s: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipamConfigSetToIpamConfigs(ipamConfigSet *schema.Set) []dc.IPAMConfig {
|
||||||
|
ipamConfigs := make([]dc.IPAMConfig, ipamConfigSet.Len())
|
||||||
|
|
||||||
|
for i, ipamConfigInt := range ipamConfigSet.List() {
|
||||||
|
ipamConfigRaw := ipamConfigInt.(map[string]interface{})
|
||||||
|
|
||||||
|
ipamConfig := dc.IPAMConfig{}
|
||||||
|
ipamConfig.Subnet = ipamConfigRaw["subnet"].(string)
|
||||||
|
ipamConfig.IPRange = ipamConfigRaw["ip_range"].(string)
|
||||||
|
ipamConfig.Gateway = ipamConfigRaw["gateway"].(string)
|
||||||
|
|
||||||
|
auxAddressRaw := ipamConfigRaw["aux_address"].(map[string]interface{})
|
||||||
|
ipamConfig.AuxAddress = make(map[string]string, len(auxAddressRaw))
|
||||||
|
for k, v := range auxAddressRaw {
|
||||||
|
ipamConfig.AuxAddress[k] = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipamConfigs[i] = ipamConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipamConfigs
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
dc "github.com/fsouza/go-dockerclient"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDockerNetwork_basic(t *testing.T) {
|
||||||
|
var n dc.Network
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccDockerNetworkConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccNetwork("docker_network.foo", &n),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccNetwork(n string, network *dc.Network) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
client := testAccProvider.Meta().(*dc.Client)
|
||||||
|
networks, err := client.ListNetworks()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range networks {
|
||||||
|
if n.ID == rs.Primary.ID {
|
||||||
|
inspected, err := client.NetworkInfo(n.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Network could not be obtained: %s", err)
|
||||||
|
}
|
||||||
|
*network = *inspected
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Network not found: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccDockerNetworkConfig = `
|
||||||
|
resource "docker_network" "foo" {
|
||||||
|
name = "bar"
|
||||||
|
}
|
||||||
|
`
|
|
@ -69,6 +69,7 @@ The following arguments are supported:
|
||||||
* `log_opts` - (Optional) Key/value pairs to use as options for the logging
|
* `log_opts` - (Optional) Key/value pairs to use as options for the logging
|
||||||
driver.
|
driver.
|
||||||
* `network_mode` - (Optional) Network mode of the container.
|
* `network_mode` - (Optional) Network mode of the container.
|
||||||
|
* `networks` - (Optional, set of strings) Id of the networks in which the container is.
|
||||||
|
|
||||||
<a id="ports"></a>
|
<a id="ports"></a>
|
||||||
## Ports
|
## Ports
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
---
|
||||||
|
layout: "docker"
|
||||||
|
page_title: "Docker: docker_network"
|
||||||
|
sidebar_current: "docs-docker-resource-network"
|
||||||
|
description: |-
|
||||||
|
Manages a Docker Network.
|
||||||
|
---
|
||||||
|
|
||||||
|
# docker\_network
|
||||||
|
|
||||||
|
Manages a Docker Network. This can be used alongside
|
||||||
|
[docker\_container](/docs/providers/docker/r/container.html)
|
||||||
|
to create virtual networks within the docker environment.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
# Find the latest Ubuntu precise image.
|
||||||
|
resource "docker_network" "private_network" {
|
||||||
|
name = "my_network"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Access it somewhere else with ${docker_image.docker_network.name}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required, string) The name of the Docker network.
|
||||||
|
* `check_duplicate` - (Optional, boolean) Requests daemon to check for networks with same name.
|
||||||
|
* `driver` - (Optional, string) Name of the network driver to use. Defaults to `bridge` driver.
|
||||||
|
* `options` - (Optional, map of strings) Network specific options to be used by the drivers.
|
||||||
|
* `ipam_driver` - (Optional, string) Driver used by the custom IP scheme of the network.
|
||||||
|
* `ipam_config` - (Optional, block) Configuration of the custom IP scheme of the network.
|
||||||
|
|
||||||
|
The `ipam_config` block supports:
|
||||||
|
|
||||||
|
* `subnet` - (Optional, string)
|
||||||
|
* `ip_range` - (Optional, string)
|
||||||
|
* `gateway` - (Optional, string)
|
||||||
|
* `aux_address` - (Optional, map of string)
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported in addition to the above configuration:
|
||||||
|
|
||||||
|
* `id` (string)
|
||||||
|
* `scope` (string)
|
|
@ -20,6 +20,10 @@
|
||||||
<li<%= sidebar_current("docs-docker-resource-image") %>>
|
<li<%= sidebar_current("docs-docker-resource-image") %>>
|
||||||
<a href="/docs/providers/docker/r/image.html">docker_image</a>
|
<a href="/docs/providers/docker/r/image.html">docker_image</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-docker-resource-network") %>>
|
||||||
|
<a href="/docs/providers/docker/r/network.html">docker_network</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
Loading…
Reference in New Issue