diff --git a/builtin/providers/docker/resource_docker_image_funcs.go b/builtin/providers/docker/resource_docker_image_funcs.go index 454113c5f..cccb37dcf 100644 --- a/builtin/providers/docker/resource_docker_image_funcs.go +++ b/builtin/providers/docker/resource_docker_image_funcs.go @@ -41,10 +41,49 @@ func resourceDockerImageUpdate(d *schema.ResourceData, meta interface{}) error { } func resourceDockerImageDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*dc.Client) + err := removeImage(d, client) + if err != nil { + return fmt.Errorf("Unable to remove Docker image: %s", err) + } d.SetId("") return nil } +func searchLocalImages(data Data, imageName string) *dc.APIImages { + if apiImage, ok := data.DockerImages[imageName]; ok { + return apiImage + } + if apiImage, ok := data.DockerImages[imageName+":latest"]; ok { + imageName = imageName + ":latest" + return apiImage + } + return nil +} + +func removeImage(d *schema.ResourceData, client *dc.Client) error { + var data Data + if err := fetchLocalImages(&data, client); err != nil { + return err + } + + imageName := d.Get("name").(string) + if imageName == "" { + return fmt.Errorf("Empty image name is not allowed") + } + + foundImage := searchLocalImages(data, imageName) + + if foundImage != nil { + err := client.RemoveImage(foundImage.ID) + if err != nil { + return err + } + } + + return nil +} + func fetchLocalImages(data *Data, client *dc.Client) error { images, err := client.ListImages(dc.ListImagesOptions{All: false}) if err != nil { @@ -146,18 +185,7 @@ func findImage(d *schema.ResourceData, client *dc.Client) (*dc.APIImages, error) return nil, fmt.Errorf("Empty image name is not allowed") } - searchLocal := func() *dc.APIImages { - if apiImage, ok := data.DockerImages[imageName]; ok { - return apiImage - } - if apiImage, ok := data.DockerImages[imageName+":latest"]; ok { - imageName = imageName + ":latest" - return apiImage - } - return nil - } - - foundImage := searchLocal() + foundImage := searchLocalImages(data, imageName) if d.Get("keep_updated").(bool) || foundImage == nil { if err := pullImage(&data, client, imageName); err != nil { @@ -165,7 +193,7 @@ func findImage(d *schema.ResourceData, client *dc.Client) (*dc.APIImages, error) } } - foundImage = searchLocal() + foundImage = searchLocalImages(data, imageName) if foundImage != nil { return foundImage, nil } diff --git a/builtin/providers/docker/resource_docker_image_test.go b/builtin/providers/docker/resource_docker_image_test.go index 67c5317c2..23e535f9e 100644 --- a/builtin/providers/docker/resource_docker_image_test.go +++ b/builtin/providers/docker/resource_docker_image_test.go @@ -1,18 +1,22 @@ package docker import ( + "fmt" "regexp" "testing" + dc "github.com/fsouza/go-dockerclient" "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" ) var contentDigestRegexp = regexp.MustCompile(`\A[A-Za-z0-9_\+\.-]+:[A-Fa-f0-9]+\z`) func TestAccDockerImage_basic(t *testing.T) { resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccDockerImageDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: testAccDockerImageConfig, @@ -26,8 +30,9 @@ func TestAccDockerImage_basic(t *testing.T) { func TestAccDockerImage_private(t *testing.T) { resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccDockerImageDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: testAddDockerPrivateImageConfig, @@ -39,6 +44,25 @@ func TestAccDockerImage_private(t *testing.T) { }) } +func testAccDockerImageDestroy(s *terraform.State) error { + //client := testAccProvider.Meta().(*dc.Client) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "docker_image" { + continue + } + + client := testAccProvider.Meta().(*dc.Client) + _, err := client.InspectImage(rs.Primary.Attributes["latest"]) + if err == nil { + return fmt.Errorf("Image still exists") + } else if err != dc.ErrNoSuchImage { + return err + } + } + return nil +} + const testAccDockerImageConfig = ` resource "docker_image" "foo" { name = "alpine:3.1"