opentofu/builtin/providers/docker/resource_docker_container.go
Jeff Mitchell f7512ca29f Initial commit. This adds the initial bits of a Docker provider.
Docker's API is huge and only a small subset is currently implemented,
but this is expected to grow over time. Currently it's enough to
satisfy the use cases of probably 95% of Docker users.

I'm preparing this initial pull request as a preview step for feedback.
My ideal scenario would be to develop this within a branch in the main
repository; the more eyes and testing and pitching in on the code, the
better (this would avoid a merge request-to-the-merge-request scenario,
as I figure this will be built up over the longer term, even before
a merge into master).

Unit tests do not exist yet. Right now I've just been focused on getting
initial functionality ported over. I've been testing each option
extensively via the Docker inspect capabilities.

This code (C)2014-2015 Akamai Technologies, Inc. <opensource@akamai.com>
2015-03-10 15:38:52 +00:00

223 lines
4.9 KiB
Go

package docker
import (
"bytes"
"fmt"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceDockerContainer() *schema.Resource {
return &schema.Resource{
Create: resourceDockerContainerCreate,
Read: resourceDockerContainerRead,
Update: resourceDockerContainerUpdate,
Delete: resourceDockerContainerDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
// Indicates whether the container must be running.
//
// An assumption is made that configured containers
// should be running; if not, they should not be in
// the configuration. Therefore a stopped container
// should be started. Set to false to have the
// provider leave the container alone.
//
// Actively-debugged containers are likely to be
// stopped and started manually, and Docker has
// some provisions for restarting containers that
// stop. The utility here comes from the fact that
// this will delete and re-create the container
// following the principle that the containers
// should be pristine when started.
"must_run": &schema.Schema{
Type: schema.TypeBool,
Default: true,
Optional: true,
},
// ForceNew is not true for image because we need to
// sane this against Docker image IDs, as each image
// can have multiple names/tags attached do it.
"image": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"hostname": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"domainname": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"command": &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"dns": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: stringSetHash,
},
"publish_all_ports": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
},
"volumes": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: getVolumesElem(),
Set: resourceDockerVolumesHash,
},
"ports": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: getPortsElem(),
Set: resourceDockerPortsHash,
},
"env": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: stringSetHash,
},
},
}
}
func getVolumesElem() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"from_container": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"container_path": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"host_path": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"read_only": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
},
},
}
}
func getPortsElem() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"internal": &schema.Schema{
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
"external": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"ip": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"protocol": &schema.Schema{
Type: schema.TypeString,
Default: "tcp",
Optional: true,
ForceNew: true,
},
},
}
}
func resourceDockerPortsHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%v-", m["internal"].(int)))
if v, ok := m["external"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(int)))
}
if v, ok := m["ip"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["protocol"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
return hashcode.String(buf.String())
}
func resourceDockerVolumesHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
if v, ok := m["from_container"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["container_path"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["host_path"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["read_only"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(bool)))
}
return hashcode.String(buf.String())
}
func stringSetHash(v interface{}) int {
return hashcode.String(v.(string))
}