kreuzwerker / terraform-provider-docker

Terraform Docker provider
Mozilla Public License 2.0
609 stars 187 forks source link

`docker_tag` does not detect changes when the `docker_image` referenced by `source_image` changes #567

Open labmonkey42 opened 1 year ago

labmonkey42 commented 1 year ago

Community Note

Terraform (and docker Provider) Version

1.3.9

Affected Resource(s)

Terraform Configuration Files

provider "docker" {
  registry_auth {
    address = "registry1.example.org"
  }
  registry_auth {
    address = "registry2.example.org"
  }
}

data "docker_registry_image" "upstream" {
  name = "registry1.example.org/ns/foo:latest"
}

resource "docker_image" "local" {
  name          = data.docker_registry_image.upstream.name
  pull_triggers = [data.docker_registry_image.upstream.sha256_digest]
}

resource "docker_tag" "server" {
  source_image = docker_image.local.name
  target_image = "registry2.example.org/ns/foo:success"
}

resource "docker_registry_image" "push" {
  keep_remotely = true
  name          = docker_tag.server.target_image

  depends_on = [
    docker_image.local
  ]
}

Expected Behaviour

Any change to the upstream image at registry1.example.org/ns/foo:latest should ultimately result in a copy at registry2.example.org/ns/foo:success.

Actual Behaviour

A change to the upstream image at registry1.example.org/ns/foo:latest is detected by the upstream data source and successfully triggers the local image resource to pull the image to the local docker instance. In my case, this is an ephemeral build server instance which disappears after the build pipeline regardless of success for failure, so this is seen as a new resource at every plan.

However, because the values of the docker_tag's source_image and target_image technically never change, the docker_tag resource never detects source image change and thus the image is never published to registry2....

avbenavides commented 11 months ago

Would be very nice to add a triggers property like docker_registry_image so it is revalidated against the sha, for example.
My workaround is to taint the tag but that of course is manual 🤮

carchi1a commented 11 months ago

@labmonkey42 I fully agree that it would be nice for the docker_tag resource to have a triggers parameter that mimics the functionality of other resources like docker_image and docker_registry_image.

In the meantime, I managed to implement a workaround using Terraform's replace_triggered_by. If you're on Terraform >= 1.2 this might work for you too:

data "docker_registry_image" "upstream" {
  name = "registry1.example.org/ns/foo:latest"
}

resource "docker_image" "local" {
  name          = data.docker_registry_image.upstream.name
  pull_triggers = [data.docker_registry_image.upstream.sha256_digest]
}

resource "docker_tag" "server" {
  source_image = docker_image.local.name
  target_image = "registry2.example.org/ns/foo:success"

  lifecycle {
    replace_triggered_by = [
      docker_image.local.repo_digest
    ]
  }
}

resource "docker_registry_image" "push" {
  keep_remotely = true
  name          = docker_tag.server.target_image

  triggers = {
    source_image_hash = docker_tag.server.source_image_id
  }
}

Hope this helps!