diff --git a/CHANGELOG.md b/CHANGELOG.md index 60f7dce0..7bd618ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.7.2 (August 8, 2024). Tested on Artifactory 7.90.6 with Terraform 1.9.3 and OpenTofu 1.8.1 + +IMPROVEMENTS: + +* resource/project: Update documentation for `repos` attribute and "Adding repositories to the project" guide to reflect new way of assigning repository to project. PR: [#152](https://github.com/jfrog/terraform-provider-project/pull/152) + ## 1.7.1 (July 25, 2024) BUG FIXES: diff --git a/docs/guides/repositories_in_project.md b/docs/guides/repositories_in_project.md index 274f16a4..8f9871aa 100644 --- a/docs/guides/repositories_in_project.md +++ b/docs/guides/repositories_in_project.md @@ -2,43 +2,34 @@ page_title: "Adding repositories to the project" --- -The guide provides information and the example on how to add repositories to the project. +The guide provides information and the example on how to add repositories to the project. -## Artifactory behavior +## Resources creation sequence -The attribute `project_environments` (`environments` in the API call) is ignored by Artifactory, if the repository is not assigned to an existing project. -That attribute can only be set to the repository if it's assigned to the project already. -The project can't be created with the list of non-existing repositories, and the repository can't be assigned to non-existing project. -Thus, if the project and the repository/repositories are created at the same time in one Terraform configuration, we have a state drift -for the `project_environments` attribute. +1. Create `project` resource +2. Create repository resource(s), the ordering of these first 2 steps doesn't matter. +3. Create `project_repository` resource, using attributes from #1 and #2 as reference values for this resource -This is happening, because the repositories need to be created first, then the project with the list of repositories gets -created. Since `project_environments` attribute is ignored in the first step, we will only have this attribute in the Terraform state, and -not in the actual repository properties. +## Artifactory repository state drift -On the next step, when the repo gets assigned to the project by the project resource, the default value `DEV` is assigned to -repositories' `project_environments` attribute. If the desired value on the first step was `DEV`, then the values match and no state -drift occurs. But if the desired value was `PROD`, we will get an error message when updating the config by `terraform plan`/`terraform apply`. +When a repository in Artifactory is assigned to a project, the API field `projectKey` is set with the project's key. While using the `project_key` attribute in the Artifactory provider to set the project key for the repository is possible, we **strongly** recommend using the `project_repository` resource instead. -``` - # artifactory_local_docker_v2_repository.docker-v2-local will be updated in-place - ~ resource "artifactory_local_docker_v2_repository" "docker-v2-local" { - id = "myproj-docker-v2-local" - ~ project_environments = [ - - "DEV", - + "PROD", - ] - } -``` - -## Workaround +However the next time `terraform plan` or `terraform apply` is run, a state drift will occur for the `project_key` attribute. To avoid this, use Terraform meta argument `lifecycle.ignore_changes`. e.g. -~> In the Project provider documentation, we strongly recommend using the `repos` attribute to manage the list of repositories. -Do not use `project_key` attribute of the repository resource. +```hcl +resource "artifactory_local_docker_v2_repository" "docker-v2-local" { + key = "myproj-docker-v2-local" + tag_retention = 3 + max_unique_tags = 5 + project_environments = ["PROD"] -Unfortunately, we can't fix the behavior described above right now. The workaround is simply to run `terraform apply` twice. -When the user applies the configuration second time, the repository is already assigned to the project, and `project_environments` -attribute won't be ignored. + lifecycle { + ignore_changes = [ + project_key + ] + } +} +``` ## Full HCL example @@ -46,31 +37,22 @@ attribute won't be ignored. terraform { required_providers { artifactory = { - source = "registry.terraform.io/jfrog/artifactory" - version = "6.21.4" + source = "jfrog/artifactory" + version = "11.5.0" } project = { - source = "registry.terraform.io/jfrog/project" - version = "1.1.1" + source = "jfrog/project" + version = "1.7.1" } } } provider "artifactory" { - // supply ARTIFACTORY_ACCESS_TOKEN / JFROG_ACCESS_TOKEN / ARTIFACTORY_API_KEY and ARTIFACTORY_URL / JFROG_URL as env vars + // supply JFROG_ACCESS_TOKEN / JFROG_URL as env vars } -resource "artifactory_local_docker_v2_repository" "docker-v2-local" { - key = "myproj-docker-v2-local" - tag_retention = 3 - max_unique_tags = 5 - project_environments = ["PROD"] - - lifecycle { - ignore_changes = [ - project_key - ] - } +provider "project" { + // supply JFROG_ACCESS_TOKEN / JFROG_URL as env vars } resource "project" "myproject" { @@ -85,11 +67,23 @@ resource "project" "myproject" { max_storage_in_gibibytes = 10 block_deployments_on_limit = false email_notification = true +} - repos = ["myproj-docker-v2-local"] +resource "artifactory_local_docker_v2_repository" "docker-v2-local" { + key = "docker-v2-local" + tag_retention = 3 + max_unique_tags = 5 + project_environments = ["PROD"] - depends_on = [ artifactory_local_docker_v2_repository.docker-v2-local ] + lifecycle { + ignore_changes = [ + project_key + ] + } } + +resource "project_repository" "myproject-docker-v2-local" { + project_key = project.myproject.key + key = artifactory_local_docker_v2_repository.docker-v2-local.key +} ``` -~> Apply `lifecycle.ignore_changes` to `project_key` attribute, otherwise it will be removed from the repository, -which means it will be unassigned from the project on the configuration update. diff --git a/docs/resources/project.md b/docs/resources/project.md index 218a3ebb..8b5541d0 100644 --- a/docs/resources/project.md +++ b/docs/resources/project.md @@ -5,7 +5,7 @@ subcategory: "" description: |- Provides an Artifactory project resource. This can be used to create and manage Artifactory project, maintain users/groups/roles/repos. Repository Configuration - After the project configuration is applied, the repository's attributes project_key and project_environments would be updated with the project's data. This will generate a state drift in the next Terraform plan/apply for the repository resource. To avoid this, apply lifecycle.ignore_changes: + After the project configuration is applied with `repos` attribute set, the repository's attributes project_key and project_environments would be updated with the project's data. This will generate a state drift in the next Terraform plan/apply for the repository resource. To avoid this, apply lifecycle.ignore_changes: ```hcl resource "artifactorylocalmavenrepository" "mymaven_releases" { key = "my-maven-releases" @@ -19,7 +19,8 @@ description: |- } ``` - ~>We strongly recommend using the 'repos' attribute to manage the list of repositories. See below for additional details. + + ~>We strongly recommend using the 'preject_repository' resource instead to manage the list of repositories. --- # project (Resource) @@ -28,7 +29,7 @@ Provides an Artifactory project resource. This can be used to create and manage ## Repository Configuration -After the project configuration is applied, the repository's attributes `project_key` and `project_environments` would be updated with the project's data. This will generate a state drift in the next Terraform plan/apply for the repository resource. To avoid this, apply `lifecycle.ignore_changes`: +After the project configuration is applied with `repos` attribute set, the repository's attributes `project_key` and `project_environments` would be updated with the project's data. This will generate a state drift in the next Terraform plan/apply for the repository resource. To avoid this, apply `lifecycle.ignore_changes`: ```hcl resource "artifactory_local_maven_repository" "my_maven_releases" { key = "my-maven-releases" @@ -42,7 +43,8 @@ resource "artifactory_local_maven_repository" "my_maven_releases" { } } ``` -~>We strongly recommend using the 'repos' attribute to manage the list of repositories. See below for additional details. + +~>We strongly recommend using the 'preject_repository' resource instead to manage the list of repositories. ## Example Usage @@ -81,7 +83,7 @@ resource "project" "myproject" { - `group` (Block Set, Deprecated) Project group. Element has one to one mapping with the [JFrog Project Groups API](https://www.jfrog.com/confluence/display/JFROG/Artifactory+REST+API#ArtifactoryRESTAPI-UpdateGroupinProject) (see [below for nested schema](#nestedblock--group)) - `max_storage_in_gibibytes` (Number) Storage quota in GiB. Must be 1 or larger. Set to -1 for unlimited storage. This is translated to binary bytes for Artifactory API. So for a 1TB quota, this should be set to 1024 (vs 1000) which will translate to 1099511627776 bytes for the API. - `member` (Block Set, Deprecated) Member of the project. Element has one to one mapping with the [JFrog Project Users API](https://www.jfrog.com/confluence/display/JFROG/Artifactory+REST+API#ArtifactoryRESTAPI-UpdateUserinProject). (see [below for nested schema](#nestedblock--member)) -- `repos` (Set of String, Deprecated) (Optional) List of existing repo keys to be assigned to the project. **Note** We *strongly* recommend using this attribute to manage the list of repositories. If you wish to use the alternate method of setting `project_key` attribute in each `artifactory_*_repository` resource in the `artifactory` provider, you will need to use `lifecycle.ignore_changes` in the `project` resource to avoid state drift. +- `repos` (Set of String, Deprecated) (Optional) List of existing repo keys to be assigned to the project. If you wish to use the alternate method of setting `project_key` attribute in each `artifactory_*_repository` resource in the `artifactory` provider, you will need to use `lifecycle.ignore_changes` in the `project` resource to avoid state drift. ```hcl lifecycle { diff --git a/pkg/project/resource/resource_project.go b/pkg/project/resource/resource_project.go index bd3a940c..aa919224 100644 --- a/pkg/project/resource/resource_project.go +++ b/pkg/project/resource/resource_project.go @@ -686,7 +686,7 @@ func (r *ProjectResource) Schema(ctx context.Context, req resource.SchemaRequest Validators: []validator.Set{ setvalidator.SizeAtLeast(1), }, - Description: "(Optional) List of existing repo keys to be assigned to the project. **Note** We *strongly* recommend using this attribute to manage the list of repositories. If you wish to use the alternate method of setting `project_key` attribute in each `artifactory_*_repository` resource in the `artifactory` provider, you will need to use `lifecycle.ignore_changes` in the `project` resource to avoid state drift.\n\n```hcl\nlifecycle {\n\tignore_changes = [\n\t\trepos\n\t]\n}\n```", + Description: "(Optional) List of existing repo keys to be assigned to the project. If you wish to use the alternate method of setting `project_key` attribute in each `artifactory_*_repository` resource in the `artifactory` provider, you will need to use `lifecycle.ignore_changes` in the `project` resource to avoid state drift.\n\n```hcl\nlifecycle {\n\tignore_changes = [\n\t\trepos\n\t]\n}\n```", DeprecationMessage: "Replaced by `project_repository` resource. This should not be used in combination with `project_repository` resource. Use `use_project_repository_resource` attribute to control which resource manages project repositories.", }, }),