diff --git a/backends/dockerclient.go b/backends/dockerclient.go index 50960a760d..320ec9c12f 100644 --- a/backends/dockerclient.go +++ b/backends/dockerclient.go @@ -106,21 +106,25 @@ func (b *dockerClientBackend) ls() ([]string, error) { return names, nil } -func (b *dockerClientBackend) spawn(cmd ...string) (beam.Sender, error) { - if len(cmd) != 1 { +func (b *dockerClientBackend) createContainer(cmd ...string) (beam.Sender, error) { + if len(cmd) != 1 { return nil, fmt.Errorf("dockerclient: spawn takes exactly 1 argument, got %d", len(cmd)) } + resp, err := b.client.call("POST", "/containers/create", cmd[0]) if err != nil { return nil, err } + respBody, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } - if resp.StatusCode != 201 { + + if resp.StatusCode == 404 { return nil, fmt.Errorf("expected status code 201, got %d:\n%s", resp.StatusCode, respBody) - } + } + var respJson struct{ Id string } if err = json.Unmarshal(respBody, &respJson); err != nil { return nil, err @@ -128,6 +132,57 @@ func (b *dockerClientBackend) spawn(cmd ...string) (beam.Sender, error) { return b.newContainer(respJson.Id), nil } +func (b *dockerClientBackend) createImage(cmd ...string) error { + if len(cmd) != 1 { + return fmt.Errorf("dockerclient: image name is the only expected argument, got %d", len(cmd)) + } + + var respJson struct{ Image string } + if err := json.Unmarshal([]byte(cmd[0]), &respJson); err != nil { + return err + } + + imageTag := strings.Split(respJson.Image, ":") + + var tag = "latest" + image := imageTag[0] + + if len(imageTag) > 1 { + tag = imageTag[1] + } + + url := fmt.Sprintf("/images/create?fromImage=%s&tag=%s", image, tag) + + resp, err := b.client.call("POST", url, "") + if err != nil { + return err + } + + _, err = ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +func (b *dockerClientBackend) spawn(cmd ...string) (beam.Sender, error) { + sender, err := b.createContainer(cmd...) + + if err != nil { + err = b.createImage(cmd...) + if err != nil { + return sender, err + } + sender, err = b.createContainer(cmd...) + if err != nil { + return sender, err + } + } + + return sender, nil +} + func (b *dockerClientBackend) newContainer(id string) beam.Sender { c := &container{backend: b, id: id} instance := beam.NewServer()