test {
  parallel = true
}

run "read_policy_with_global_actions" {
  state_key = "read_policy_with_global_actions"
  command   = plan

  variables {
    repositories = [
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ]
    action_types          = ["read"]
    enable_global_actions = true
  }

  assert {
    condition     = length(jsondecode(output.policy.json)["Statement"]) == 2
    error_message = "Unexpected number of statements in policy."
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][0]["Resource"]) == toset([
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ])
    error_message = "Resource ARNs in repository actions statement do not match expected values"
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][0]["Action"]) == toset([
      "ecr:BatchCheckLayerAvailability",
      "ecr:BatchGetImage",
      "ecr:DescribeImages",
      "ecr:DescribeImageScanFindings",
      "ecr:GetDownloadUrlForLayer",
      "ecr:GetLifecyclePolicy",
      "ecr:GetLifecyclePolicyPreview",
      "ecr:GetRepositoryPolicy",
      "ecr:ListImages",
      "ecr:ListTagsForResource",
    ])
    error_message = "Actions in repository actions statement do not match expected values"
  }

  assert {
    condition     = jsondecode(output.policy.json)["Statement"][1]["Resource"] == "*"
    error_message = "Resource ARN in global actions statement does not match expected value"
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][1]["Action"]) == toset([
      "ecr:GetAuthorizationToken",
      "ecr:DescribeRepositories",
    ])
    error_message = "Actions in global actions statement do not match expected values"
  }
}

run "read_policy_without_global_actions" {
  state_key = "read_policy_without_global_actions"
  command   = plan

  variables {
    repositories = [
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ]
    action_types          = ["read"]
    enable_global_actions = false
  }

  assert {
    condition     = length(jsondecode(output.policy.json)["Statement"]) == 1
    error_message = "Unexpected number of statements in policy."
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][0]["Resource"]) == toset([
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ])
    error_message = "Resource ARN in repository actions statement does not match expected value"
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][0]["Action"]) == toset([
      "ecr:BatchCheckLayerAvailability",
      "ecr:BatchGetImage",
      "ecr:DescribeImages",
      "ecr:DescribeImageScanFindings",
      "ecr:GetDownloadUrlForLayer",
      "ecr:GetLifecyclePolicy",
      "ecr:GetLifecyclePolicyPreview",
      "ecr:GetRepositoryPolicy",
      "ecr:ListImages",
      "ecr:ListTagsForResource",
    ])
    error_message = "Actions in repository actions statement do not match expected values"
  }
}

run "write_policy_with_global_actions" {
  state_key = "write_policy_with_global_actions"
  command   = plan

  variables {
    repositories = [
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ]
    action_types          = ["write"]
    enable_global_actions = true
  }

  assert {
    condition     = length(jsondecode(output.policy.json)["Statement"]) == 1
    error_message = "Unexpected number of statements in policy."
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][0]["Resource"]) == toset([
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ])
    error_message = "Resource ARNs in repository actions statement do not match expected values"
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][0]["Action"]) == toset([
      "ecr:CompleteLayerUpload",
      "ecr:InitiateLayerUpload",
      "ecr:PutImage",
      "ecr:UploadLayerPart",
    ])
    error_message = "Actions in repository actions statement do not match expected values"
  }
}

run "write_policy_without_global_actions" {
  state_key = "write_policy_without_global_actions"
  command   = plan

  variables {
    repositories = [
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ]
    action_types          = ["write"]
    enable_global_actions = false
  }

  assert {
    condition     = length(jsondecode(output.policy.json)["Statement"]) == 1
    error_message = "Unexpected number of statements in policy."
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][0]["Resource"]) == toset([
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ])
    error_message = "Resource ARN in repository actions statement do not match expected value"
  }

  assert {
    condition = toset(jsondecode(output.policy.json)["Statement"][0]["Action"]) == toset([
      "ecr:CompleteLayerUpload",
      "ecr:InitiateLayerUpload",
      "ecr:PutImage",
      "ecr:UploadLayerPart",
    ])
    error_message = "Actions in repository actions statement do not match expected values"
  }
}

run "delete_policy_with_global_actions" {
  state_key = "delete_policy_with_global_actions"
  command   = plan

  variables {
    repositories = [
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ]
    action_types          = ["delete"]
    enable_global_actions = true
  }

  # Expect this to fail because the policy will have no statements
  expect_failures = [
    data.aws_iam_policy_document.policy
  ]
}

run "delete_policy_without_global_actions" {
  state_key = "delete_policy_without_global_actions"
  command   = plan

  variables {
    repositories = [
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo1",
      "arn:aws:ecr:us-east-1:123456789012:repository/my-repo2"
    ]
    action_types          = ["delete"]
    enable_global_actions = false
  }

  # Expect this to fail because the policy will have no statements
  expect_failures = [
    data.aws_iam_policy_document.policy
  ]
}
