Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update 'project.repos' doc and guide #152

Merged
merged 3 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
94 changes: 44 additions & 50 deletions docs/guides/repositories_in_project.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,57 @@
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

```hcl
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" {
Expand All @@ -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.
12 changes: 7 additions & 5 deletions docs/resources/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
Expand All @@ -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"
Expand All @@ -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

Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion pkg/project/resource/resource_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
},
}),
Expand Down
Loading