Answers: <p>In your <code>terraform {...}</code> section you need a backend directive to store your state somewhere: <a href="https://www.terraform.io/docs/state/remote.html" rel="nofollow noreferrer">https://www.terraform.io/docs/state/remote.html</a> (OP later explain that the code above is just a module imported from a main file).</p>
  
  <p><a href="https://www.terraform.io/docs/backends/types/s3.html" rel="nofollow noreferrer">S3 backends</a> might be the easiest to use and probably to most commonly used backends to store remote state across different executions of Terraform:</p>
  
  <pre><code>terraform {
    backend "s3" {
      bucket = "mybucket"
      key    = "path/to/my/key"
      region = "us-east-1"
    }
  }
  </code></pre>
  
  <p>Please note that Terraform <a href="https://www.terraform.io/docs/commands/init.html" rel="nofollow noreferrer">init</a> will not import existing resources into a state (there's Terraform <a href="https://www.terraform.io/docs/import/" rel="nofollow noreferrer">import</a> for that). It will therefore try to create new ones and you will get a conflict on the name. The Terraform documentation gives some pointers on <a href="https://learn.hashicorp.com/terraform/development/running-terraform-in-automation" rel="nofollow noreferrer">how to use Terraform in automation</a> and that includes using remote state.</p>
  
  <p>It is possible to prevent the creation of the ECR through a data block as you hinted (with <code>count = ...</code>), but doing so would feel like a hack to me.</p>
  
  <p>Once you have your remote backend configured, you can double check that everything works as expected by using the <code>terraform state</code> command in your pipeline. I would suggest using the show subcommand on a resource you expect to be there in order to validate that the state indeed contains the resource:</p>
  
  <pre><code>terraform init -input=false
  terraform state show module.name-of-your-module.aws_ecr_repository.frontend_ecr_repo_creation
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2019-07-03T08:36:09.077Z
Answers: My Terraform code listed above is a module which is referenced by my main.tf file in the root directory of my Terraform repository which defines the terraform backend directive - As mentioned in my OP, I am satisfied that my state file is being updated correctly.
Answers: jto
Answers: CC BY-SA 4.0
Answers: 2019-07-03T14:04:48.857Z
Answers: I've used your code locally and everything works as expected for me. The only way I was able to reproduce your issue is by deleting the remote state.
  
  You say you are satisfied that your state file is being updated correctly, but it really looks like it isn't. 
  
  Can you run `terraform state show module.name-of-your-module.aws_ecr_repository.frontend_ecr_repo_creation` right after your init?
Answers: Alexandre
Answers: CC BY-SA 4.0
Answers: 2019-07-05T13:32:11.563Z
Answers: Apologies, you were indeed correct. I can't believe I overlooked that - Easiest bounty ever haha - This section of code wasn't part of the module I thought it was (unfamiliar codebase) and was instead in it's own directory without a state file!
Answers: jto
Answers: CC BY-SA 4.0
Answers: 2019-07-02T19:05:09.823Z
Answers: 2019-07-03T14:16:16.463Z
Answers: 2019-07-03T14:16:16.463Z
Answers: Alexandre
Body: <p>I have been banging my head against this seemingly simple issue for awhile now. I have some Terraform code which sets up an ECR repository, policy and lifecycle policy.</p>
  
  <pre><code>provider "aws" {
      region = "${var.region_id}"
  }
  
  terraform {
     required_version = "0.11.13"
  }
  
  resource "aws_ecr_repository" "frontend_ecr_repo_creation" {
    name = "${var.app_image}"
  }
  
  resource "aws_ecr_repository_policy" "frontend_ecr_policy" {
    repository = "${aws_ecr_repository.frontend_ecr_repo_creation.name}"
  
    policy = &lt;&lt;EOF
  {
      "Version": "2008-10-17",
      "Statement": [
          {
              "Sid": "new policy",
              "Effect": "Allow",
              "Principal": "*",
              "Action": [
                  "ecr:GetDownloadUrlForLayer",
                  "ecr:BatchGetImage",
                  "ecr:BatchCheckLayerAvailability",
                  "ecr:PutImage",
                  "ecr:InitiateLayerUpload",
                  "ecr:UploadLayerPart",
                  "ecr:CompleteLayerUpload",
                  "ecr:DescribeRepositories",
                  "ecr:GetRepositoryPolicy",
                  "ecr:ListImages",
                  "ecr:DeleteRepository",
                  "ecr:BatchDeleteImage",
                  "ecr:SetRepositoryPolicy",
                  "ecr:DeleteRepositoryPolicy"
              ]
          }
      ]
  }
  EOF
  }
  
  resource "aws_ecr_lifecycle_policy" "frontend_ecr_lifecycle_policy" {
    repository = "${aws_ecr_repository.frontend_ecr_repo_creation.name}"
  
    policy = &lt;&lt;EOF
  {
      "rules": [
          {
              "rulePriority": 1,
              "description": "Keep last 3 images",
              "selection": {
                  "tagStatus": "any",
                  "countType": "imageCountMoreThan",
                  "countNumber": 3
              },
              "action": {
                  "type": "expire"
              }
          }
      ]
  }
  EOF
  }
  </code></pre>
  
  <p>This runs perfectly fine, however subsequent runs fail with:</p>
  
  <pre><code> aws_ecr_repository.frontend_ecr_repo_creation: error creating ECR repository: RepositoryAlreadyExistsException: The repository with name 'cwyo/master' already exists in the registry with id '720734997891'
      status code: 400, request id: cf59815c-7c9d-11e9-965d-0b326e93dee5
  </code></pre>
  
  <p>I would expect Terraform plan no changes, instead it attempts to recreate the repository. This shows all of the signs of an incorrect remote state, however I run a Terraform init in my pipeline beforehand and I am satisfied that it is correct.</p>
  
  <p>I have been working around this by adding GitLab CI's inbuilt $COMMIT_SHA variable as a prefix, this works well except lifecycle policies cannot be applied therefore I ended up with 100's of useless repositories.</p>
  
  <p>I have looked in to a data structure to check if the repository exists and add a depends_on to the resource but no luck...</p>
  
  <p><strong>How do I ensure the aws_ecr_repository resource uses an existing repository if it already exists?</strong></p>
  
Comments: CC BY-SA 4.0
Comments: 2019-07-02T12:38:44.763Z
Comments: UPDATE: I have since been using terraform import to find the existing ECR repository. This works, of course, but it does add a potential manual step in that if the ECR repository is ever deleted or we switch AWS accounts, our Terraform will fail until we manually recreate said repository...
Comments: jto
Comments: CC BY-SA 4.0
Comments: 2019-07-03T14:17:54.777Z
Comments: ' incorrect remote state, however'...'I am satisfied that it is correct.' --> It is important to add some information about the remote state in this question. It would also be very helpful to include `terraform state show <some resources>`
Comments: Alexandre
Tags: <amazon-web-services><terraform><amazon-ecs>
Title: Terraform aws_ecr_repository resource always attempts to destroy
UserDisplayName: jto
ThreadText: # Terraform aws_ecr_repository resource always attempts to destroy
  
  (Asked by: username_0 on 2019-05-22)
  
  I have been banging my head against this seemingly simple issue for awhile now. I have some Terraform code which sets up an ECR repository, policy and lifecycle policy.
  
  ```
  provider "aws" {
      region = "${var.region_id}"
  }
  
  terraform {
     required_version = "0.11.13"
  }
  
  resource "aws_ecr_repository" "frontend_ecr_repo_creation" {
    name = "${var.app_image}"
  }
  
  resource "aws_ecr_repository_policy" "frontend_ecr_policy" {
    repository = "${aws_ecr_repository.frontend_ecr_repo_creation.name}"
  
    policy = <<EOF
  {
      "Version": "2008-10-17",
      "Statement": [
          {
              "Sid": "new policy",
              "Effect": "Allow",
              "Principal": "*",
              "Action": [
                  "ecr:GetDownloadUrlForLayer",
                  "ecr:BatchGetImage",
                  "ecr:BatchCheckLayerAvailability",
                  "ecr:PutImage",
                  "ecr:InitiateLayerUpload",
                  "ecr:UploadLayerPart",
                  "ecr:CompleteLayerUpload",
                  "ecr:DescribeRepositories",
                  "ecr:GetRepositoryPolicy",
                  "ecr:ListImages",
                  "ecr:DeleteRepository",
                  "ecr:BatchDeleteImage",
                  "ecr:SetRepositoryPolicy",
                  "ecr:DeleteRepositoryPolicy"
              ]
          }
      ]
  }
  EOF
  }
  
  resource "aws_ecr_lifecycle_policy" "frontend_ecr_lifecycle_policy" {
    repository = "${aws_ecr_repository.frontend_ecr_repo_creation.name}"
  
    policy = <<EOF
  {
      "rules": [
          {
              "rulePriority": 1,
              "description": "Keep last 3 images",
              "selection": {
                  "tagStatus": "any",
                  "countType": "imageCountMoreThan",
                  "countNumber": 3
              },
              "action": {
                  "type": "expire"
              }
          }
      ]
  }
  EOF
  }
  
  ```
  
  This runs perfectly fine, however subsequent runs fail with:
  
  ```
   aws_ecr_repository.frontend_ecr_repo_creation: error creating ECR repository: RepositoryAlreadyExistsException: The repository with name 'cwyo/master' already exists in the registry with id '720734997891'
      status code: 400, request id: cf59815c-7c9d-11e9-965d-0b326e93dee5
  
  ```
  
  I would expect Terraform plan no changes, instead it attempts to recreate the repository. This shows all of the signs of an incorrect remote state, however I run a Terraform init in my pipeline beforehand and I am satisfied that it is correct.
  
  I have been working around this by adding GitLab CI's inbuilt $COMMIT\_SHA variable as a prefix, this works well except lifecycle policies cannot be applied therefore I ended up with 100's of useless repositories.
  
  I have looked in to a data structure to check if the repository exists and add a depends\_on to the resource but no luck...
  
  **How do I ensure the aws\_ecr\_repository resource uses an existing repository if it already exists?**
  
  **Tags:** amazon-web-services, terraform, amazon-ecs
  
  > **Comments:**
  > **username_0**: UPDATE: I have since been using terraform import to find the existing ECR repository. This works, of course, but it does add a potential manual step in that if the ECR repository is ever deleted or we switch AWS accounts, our Terraform will fail until we manually recreate said repository...  
  > **username_1**: ' incorrect remote state, however'...'I am satisfied that it is correct.' --> It is important to add some information about the remote state in this question. It would also be very helpful to include `terraform state show <some resources>`  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2019-07-02. Score: 1 | Accepted answer
  
  In your `terraform {...}` section you need a backend directive to store your state somewhere: <https://www.terraform.io/docs/state/remote.html> (OP later explain that the code above is just a module imported from a main file).
  
  [S3 backends](https://www.terraform.io/docs/backends/types/s3.html) might be the easiest to use and probably to most commonly used backends to store remote state across different executions of Terraform:
  
  ```
  terraform {
    backend "s3" {
      bucket = "mybucket"
      key    = "path/to/my/key"
      region = "us-east-1"
    }
  }
  
  ```
  
  Please note that Terraform [init](https://www.terraform.io/docs/commands/init.html) will not import existing resources into a state (there's Terraform [import](https://www.terraform.io/docs/import/) for that). It will therefore try to create new ones and you will get a conflict on the name. The Terraform documentation gives some pointers on [how to use Terraform in automation](https://learn.hashicorp.com/terraform/development/running-terraform-in-automation) and that includes using remote state.
  
  It is possible to prevent the creation of the ECR through a data block as you hinted (with `count = ...`), but doing so would feel like a hack to me.
  
  Once you have your remote backend configured, you can double check that everything works as expected by using the `terraform state` command in your pipeline. I would suggest using the show subcommand on a resource you expect to be there in order to validate that the state indeed contains the resource:
  
  ```
  terraform init -input=false
  terraform state show module.name-of-your-module.aws_ecr_repository.frontend_ecr_repo_creation
  
  ```
  
  > **Comments:**
  > **username_0**: My Terraform code listed above is a module which is referenced by my main.tf file in the root directory of my Terraform repository which defines the terraform backend directive - As mentioned in my OP, I am satisfied that my state file is being updated correctly.  
  > **username_1**: I've used your code locally and everything works as expected for me. The only way I was able to reproduce your issue is by deleting the remote state.  You say you are satisfied that your state file is being updated correctly, but it really looks like it isn't.   Can you run `terraform state show module.name-of-your-module.aws_ecr_repository.frontend_ecr_repo_creation` right after your init?  
  > **username_0**: Apologies, you were indeed correct. I can't believe I overlooked that - Easiest bounty ever haha - This section of code wasn't part of the module I thought it was (unfamiliar codebase) and was instead in it's own directory without a state file!  
  
  ---
  
  