diff --git a/builtin/providers/docker/resource_docker_container.go b/builtin/providers/docker/resource_docker_container.go
index 3bcf922315c2..9a7542dafcb3 100644
--- a/builtin/providers/docker/resource_docker_container.go
+++ b/builtin/providers/docker/resource_docker_container.go
@@ -2,10 +2,14 @@ package docker
import (
"bytes"
+ "crypto/sha1"
+ "encoding/hex"
"fmt"
-
+ "io"
+ "os"
"regexp"
+ "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
@@ -348,6 +352,54 @@ func resourceDockerContainer() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
+
+ "uploads": &schema.Schema{
+ Type: schema.TypeSet,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "local_path": &schema.Schema{
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
+ path := v.(string)
+ if _, err := os.Stat(path); err != nil {
+ es = append(es, fmt.Errorf(
+ "%q must be valid path: %s", path, err))
+ }
+ return
+ },
+ StateFunc: func(v interface{}) string {
+ switch v.(type) {
+ case string:
+ reader, err := archive.Tar(v.(string), archive.Uncompressed)
+ if err != nil {
+ return "invalid"
+ }
+
+ hash := sha1.New()
+ if _, err := io.Copy(hash, reader); err != nil {
+ return "invalid"
+ }
+
+ return hex.EncodeToString(hash.Sum(nil)[:])
+ default:
+ return ""
+ }
+ },
+ },
+
+ "remote_path": &schema.Schema{
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ },
+ },
+ },
+ Set: resourceDockerUploadsHash,
+ },
},
}
}
@@ -414,3 +466,18 @@ func resourceDockerVolumesHash(v interface{}) int {
return hashcode.String(buf.String())
}
+
+func resourceDockerUploadsHash(v interface{}) int {
+ var buf bytes.Buffer
+ m := v.(map[string]interface{})
+
+ if v, ok := m["local_path"]; ok {
+ buf.WriteString(fmt.Sprintf("%v-", v.(string)))
+ }
+
+ if v, ok := m["remote_path"]; ok {
+ buf.WriteString(fmt.Sprintf("%v-", v.(string)))
+ }
+
+ return hashcode.String(buf.String())
+}
diff --git a/builtin/providers/docker/resource_docker_container_funcs.go b/builtin/providers/docker/resource_docker_container_funcs.go
index 00090294c636..fdd459529b96 100644
--- a/builtin/providers/docker/resource_docker_container_funcs.go
+++ b/builtin/providers/docker/resource_docker_container_funcs.go
@@ -7,6 +7,7 @@ import (
"time"
dc "github.com/fsouza/go-dockerclient"
+ "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive"
"github.com/hashicorp/terraform/helper/schema"
)
@@ -174,6 +175,19 @@ func resourceDockerContainerCreate(d *schema.ResourceData, meta interface{}) err
}
}
+ if v, ok := d.GetOk("uploads"); ok {
+ for _, upload := range v.(*schema.Set).List() {
+ uploadOpts, err := uploadFile(upload.(map[string]interface{}))
+ if err != nil {
+ return err
+ }
+
+ if err := client.UploadToContainer(retContainer.ID, *uploadOpts); err != nil {
+ return fmt.Errorf("Unable to upload to container: %s", err)
+ }
+ }
+ }
+
creationTime = time.Now()
if err := client.StartContainer(retContainer.ID, nil); err != nil {
return fmt.Errorf("Unable to start container: %s", err)
@@ -387,3 +401,20 @@ func volumeSetToDockerVolumes(volumes *schema.Set) (map[string]struct{}, []strin
return retVolumeMap, retHostConfigBinds, retVolumeFromContainers, nil
}
+
+func uploadFile(upload map[string]interface{}) (*dc.UploadToContainerOptions, error) {
+ localPath := upload["local_path"].(string)
+ remotePath := upload["remote_path"].(string)
+
+ stream, err := archive.Tar(localPath, archive.Uncompressed)
+ if err != nil {
+ return nil, fmt.Errorf("Unable to send %s to container: %s", localPath, err)
+ }
+
+ uploadOpts := &dc.UploadToContainerOptions{
+ InputStream: stream,
+ Path: remotePath,
+ NoOverwriteDirNonDir: false,
+ }
+ return uploadOpts, nil
+}
diff --git a/website/source/docs/providers/docker/r/container.html.markdown b/website/source/docs/providers/docker/r/container.html.markdown
index 7441e88ac112..7c3916e3d987 100644
--- a/website/source/docs/providers/docker/r/container.html.markdown
+++ b/website/source/docs/providers/docker/r/container.html.markdown
@@ -77,6 +77,7 @@ The following arguments are supported:
* `network_mode` - (Optional, string) Network mode of the container.
* `networks` - (Optional, set of strings) Id of the networks in which the
container is.
+* `uploads` - (Optional) See [Uploads](#uploads) below for details.
### Ports
@@ -99,7 +100,7 @@ the extra host mappings for the container. Each `host_entry` block supports
the following:
* `host` - (Required, int) Hostname to add.
-* `ip` - (Required, int) IP address this hostname should resolve to..
+* `ip` - (Required, int) IP address this hostname should resolve to.
This is equivalent to using the `--add-host` option when using the `run`
command of the Docker CLI.
@@ -124,6 +125,17 @@ the following:
One of `from_container`, `host_path` or `volume_name` must be set.
+
+### Uploads
+
+`uploads` is a block within the configuration that can be repeated to specify
+files and directories to upload to the container before starting it.
+Each `uploads` supports the following
+
+* `local_path` - (Required, string) local path to a file or directory to upload.
+* `remote_path` - (Required, string) path to a file or directory in the
+ container.
+
## Attributes Reference
The following attributes are exported: