github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/docker/resource_docker_container.go (about)

     1  package docker
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/hashicorp/terraform/helper/hashcode"
     8  	"github.com/hashicorp/terraform/helper/schema"
     9  	"regexp"
    10  )
    11  
    12  func resourceDockerContainer() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceDockerContainerCreate,
    15  		Read:   resourceDockerContainerRead,
    16  		Update: resourceDockerContainerUpdate,
    17  		Delete: resourceDockerContainerDelete,
    18  
    19  		Schema: map[string]*schema.Schema{
    20  			"name": &schema.Schema{
    21  				Type:     schema.TypeString,
    22  				Required: true,
    23  				ForceNew: true,
    24  			},
    25  
    26  			// Indicates whether the container must be running.
    27  			//
    28  			// An assumption is made that configured containers
    29  			// should be running; if not, they should not be in
    30  			// the configuration. Therefore a stopped container
    31  			// should be started. Set to false to have the
    32  			// provider leave the container alone.
    33  			//
    34  			// Actively-debugged containers are likely to be
    35  			// stopped and started manually, and Docker has
    36  			// some provisions for restarting containers that
    37  			// stop. The utility here comes from the fact that
    38  			// this will delete and re-create the container
    39  			// following the principle that the containers
    40  			// should be pristine when started.
    41  			"must_run": &schema.Schema{
    42  				Type:     schema.TypeBool,
    43  				Default:  true,
    44  				Optional: true,
    45  			},
    46  
    47  			// ForceNew is not true for image because we need to
    48  			// sane this against Docker image IDs, as each image
    49  			// can have multiple names/tags attached do it.
    50  			"image": &schema.Schema{
    51  				Type:     schema.TypeString,
    52  				Required: true,
    53  				ForceNew: true,
    54  			},
    55  
    56  			"hostname": &schema.Schema{
    57  				Type:     schema.TypeString,
    58  				Optional: true,
    59  				ForceNew: true,
    60  			},
    61  
    62  			"domainname": &schema.Schema{
    63  				Type:     schema.TypeString,
    64  				Optional: true,
    65  				ForceNew: true,
    66  			},
    67  
    68  			"command": &schema.Schema{
    69  				Type:     schema.TypeList,
    70  				Optional: true,
    71  				ForceNew: true,
    72  				Elem:     &schema.Schema{Type: schema.TypeString},
    73  			},
    74  
    75  			"entrypoint": &schema.Schema{
    76  				Type:     schema.TypeList,
    77  				Optional: true,
    78  				ForceNew: true,
    79  				Elem:     &schema.Schema{Type: schema.TypeString},
    80  			},
    81  
    82  			"dns": &schema.Schema{
    83  				Type:     schema.TypeSet,
    84  				Optional: true,
    85  				ForceNew: true,
    86  				Elem:     &schema.Schema{Type: schema.TypeString},
    87  				Set:      stringSetHash,
    88  			},
    89  
    90  			"publish_all_ports": &schema.Schema{
    91  				Type:     schema.TypeBool,
    92  				Optional: true,
    93  				ForceNew: true,
    94  			},
    95  
    96  			"restart": &schema.Schema{
    97  				Type:     schema.TypeString,
    98  				Optional: true,
    99  				ForceNew: true,
   100  				Default:  "no",
   101  				ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
   102  					value := v.(string)
   103  					if !regexp.MustCompile(`^(no|on-failure|always)$`).MatchString(value) {
   104  						es = append(es, fmt.Errorf(
   105  							"%q must be one of \"no\", \"on-failure\", or \"always\"", k))
   106  					}
   107  					return
   108  				},
   109  			},
   110  
   111  			"max_retry_count": &schema.Schema{
   112  				Type:     schema.TypeInt,
   113  				Optional: true,
   114  				ForceNew: true,
   115  			},
   116  
   117  			"volumes": &schema.Schema{
   118  				Type:     schema.TypeSet,
   119  				Optional: true,
   120  				ForceNew: true,
   121  				Elem:     getVolumesElem(),
   122  				Set:      resourceDockerVolumesHash,
   123  			},
   124  
   125  			"ports": &schema.Schema{
   126  				Type:     schema.TypeSet,
   127  				Optional: true,
   128  				ForceNew: true,
   129  				Elem:     getPortsElem(),
   130  				Set:      resourceDockerPortsHash,
   131  			},
   132  
   133  			"env": &schema.Schema{
   134  				Type:     schema.TypeSet,
   135  				Optional: true,
   136  				ForceNew: true,
   137  				Elem:     &schema.Schema{Type: schema.TypeString},
   138  				Set:      stringSetHash,
   139  			},
   140  
   141  			"links": &schema.Schema{
   142  				Type:     schema.TypeSet,
   143  				Optional: true,
   144  				ForceNew: true,
   145  				Elem:     &schema.Schema{Type: schema.TypeString},
   146  				Set:      stringSetHash,
   147  			},
   148  
   149  			"ip_address": &schema.Schema{
   150  				Type:     schema.TypeString,
   151  				Computed: true,
   152  			},
   153  
   154  			"ip_prefix_length": &schema.Schema{
   155  				Type:     schema.TypeInt,
   156  				Computed: true,
   157  			},
   158  
   159  			"gateway": &schema.Schema{
   160  				Type:     schema.TypeString,
   161  				Computed: true,
   162  			},
   163  
   164  			"bridge": &schema.Schema{
   165  				Type:     schema.TypeString,
   166  				Computed: true,
   167  			},
   168  
   169  			"privileged": &schema.Schema{
   170  				Type:     schema.TypeBool,
   171  				Optional: true,
   172  				ForceNew: true,
   173  			},
   174  
   175  			"labels": &schema.Schema{
   176  				Type:     schema.TypeMap,
   177  				Optional: true,
   178  				ForceNew: true,
   179  			},
   180  
   181  			"memory": &schema.Schema{
   182  				Type:     schema.TypeInt,
   183  				Optional: true,
   184  				ForceNew: true,
   185  				ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
   186  					value := v.(int)
   187  					if value < 0 {
   188  						es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k))
   189  					}
   190  					return
   191  				},
   192  			},
   193  
   194  			"memory_swap": &schema.Schema{
   195  				Type:     schema.TypeInt,
   196  				Optional: true,
   197  				ForceNew: true,
   198  				ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
   199  					value := v.(int)
   200  					if value < -1 {
   201  						es = append(es, fmt.Errorf("%q must be greater than or equal to -1", k))
   202  					}
   203  					return
   204  				},
   205  			},
   206  
   207  			"cpu_shares": &schema.Schema{
   208  				Type:     schema.TypeInt,
   209  				Optional: true,
   210  				ForceNew: true,
   211  				ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
   212  					value := v.(int)
   213  					if value < 0 {
   214  						es = append(es, fmt.Errorf("%q must be greater than or equal to 0", k))
   215  					}
   216  					return
   217  				},
   218  			},
   219  
   220  			"log_driver": &schema.Schema{
   221  				Type:     schema.TypeString,
   222  				Optional: true,
   223  				ForceNew: true,
   224  				Default:  "json-file",
   225  				ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
   226  					value := v.(string)
   227  					if !regexp.MustCompile(`^(json-file|syslog|journald|gelf|fluentd)$`).MatchString(value) {
   228  						es = append(es, fmt.Errorf(
   229  							"%q must be one of \"json-file\", \"syslog\", \"journald\", \"gelf\", or \"fluentd\"", k))
   230  					}
   231  					return
   232  				},
   233  			},
   234  
   235  			"log_opts": &schema.Schema{
   236  				Type:     schema.TypeMap,
   237  				Optional: true,
   238  				ForceNew: true,
   239  			},
   240  		},
   241  	}
   242  }
   243  
   244  func getVolumesElem() *schema.Resource {
   245  	return &schema.Resource{
   246  		Schema: map[string]*schema.Schema{
   247  			"from_container": &schema.Schema{
   248  				Type:     schema.TypeString,
   249  				Optional: true,
   250  				ForceNew: true,
   251  			},
   252  
   253  			"container_path": &schema.Schema{
   254  				Type:     schema.TypeString,
   255  				Optional: true,
   256  				ForceNew: true,
   257  			},
   258  
   259  			"host_path": &schema.Schema{
   260  				Type:     schema.TypeString,
   261  				Optional: true,
   262  				ForceNew: true,
   263  			},
   264  
   265  			"read_only": &schema.Schema{
   266  				Type:     schema.TypeBool,
   267  				Optional: true,
   268  				ForceNew: true,
   269  			},
   270  		},
   271  	}
   272  }
   273  
   274  func getPortsElem() *schema.Resource {
   275  	return &schema.Resource{
   276  		Schema: map[string]*schema.Schema{
   277  			"internal": &schema.Schema{
   278  				Type:     schema.TypeInt,
   279  				Required: true,
   280  				ForceNew: true,
   281  			},
   282  
   283  			"external": &schema.Schema{
   284  				Type:     schema.TypeInt,
   285  				Optional: true,
   286  				ForceNew: true,
   287  			},
   288  
   289  			"ip": &schema.Schema{
   290  				Type:     schema.TypeString,
   291  				Optional: true,
   292  				ForceNew: true,
   293  			},
   294  
   295  			"protocol": &schema.Schema{
   296  				Type:     schema.TypeString,
   297  				Default:  "tcp",
   298  				Optional: true,
   299  				ForceNew: true,
   300  			},
   301  		},
   302  	}
   303  }
   304  
   305  func resourceDockerPortsHash(v interface{}) int {
   306  	var buf bytes.Buffer
   307  	m := v.(map[string]interface{})
   308  
   309  	buf.WriteString(fmt.Sprintf("%v-", m["internal"].(int)))
   310  
   311  	if v, ok := m["external"]; ok {
   312  		buf.WriteString(fmt.Sprintf("%v-", v.(int)))
   313  	}
   314  
   315  	if v, ok := m["ip"]; ok {
   316  		buf.WriteString(fmt.Sprintf("%v-", v.(string)))
   317  	}
   318  
   319  	if v, ok := m["protocol"]; ok {
   320  		buf.WriteString(fmt.Sprintf("%v-", v.(string)))
   321  	}
   322  
   323  	return hashcode.String(buf.String())
   324  }
   325  
   326  func resourceDockerVolumesHash(v interface{}) int {
   327  	var buf bytes.Buffer
   328  	m := v.(map[string]interface{})
   329  
   330  	if v, ok := m["from_container"]; ok {
   331  		buf.WriteString(fmt.Sprintf("%v-", v.(string)))
   332  	}
   333  
   334  	if v, ok := m["container_path"]; ok {
   335  		buf.WriteString(fmt.Sprintf("%v-", v.(string)))
   336  	}
   337  
   338  	if v, ok := m["host_path"]; ok {
   339  		buf.WriteString(fmt.Sprintf("%v-", v.(string)))
   340  	}
   341  
   342  	if v, ok := m["read_only"]; ok {
   343  		buf.WriteString(fmt.Sprintf("%v-", v.(bool)))
   344  	}
   345  
   346  	return hashcode.String(buf.String())
   347  }
   348  
   349  func stringSetHash(v interface{}) int {
   350  	return hashcode.String(v.(string))
   351  }