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

Fix backup state drift #1147

Merged
merged 4 commits into from
Dec 11, 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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ FEATURES:

**New Resource:** `artifactory_archive_policy` to support upcoming Archive Policy feature. PR: [#1146](https://github.com/jfrog/terraform-provider-artifactory/pull/1146)

BUG FIXES:

* resource/artifactory_backup: Add size validation to `excluded_repositories` attribute to ensure at least 1 item. Issue: [#1143](https://github.com/jfrog/terraform-provider-artifactory/issues/1143) PR: [#1147](https://github.com/jfrog/terraform-provider-artifactory/pull/1147)

## 12.5.1 (November 22, 2024)

BUG FIXES:
Expand Down
57 changes: 35 additions & 22 deletions docs/resources/backup.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,67 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "artifactory_backup Resource - terraform-provider-artifactory"
subcategory: "Configuration"
description: |-
This resource can be used to manage the automatic and periodic backups of the entire Artifactory instance.
When an artifactory_backup resource is configured and enabled to true, backup of the entire Artifactory system will be done automatically and periodically.
The backup process creates a time-stamped directory in the target backup directory.
See JFrog Artifactory Backup https://www.jfrog.com/confluence/display/JFROG/Backups for more details.
~>Only supported in self-hosted environment.
---
# Artifactory Backup Resource

# artifactory_backup (Resource)

This resource can be used to manage the automatic and periodic backups of the entire Artifactory instance.

When an `artifactory_backup` resource is configured and enabled to true, backup of the entire Artifactory system will be done automatically and periodically.

The backup process creates a time-stamped directory in the target backup directory.

~>The `artifactory_backup` resource utilizes endpoints which are blocked/removed in SaaS environments (i.e. in Artifactory online), rendering this resource incompatible with Artifactory SaaS environments.
See [JFrog Artifactory Backup](https://www.jfrog.com/confluence/display/JFROG/Backups) for more details.

~>Only supported in self-hosted environment.

## Example Usage

```hcl
# Configure Artifactory Backup system config
```terraform
resource "artifactory_backup" "backup_config_name" {
key = "backup_config_name"
enabled = true
cron_exp = "0 0 12 * * ? *"
retention_period_hours = 1000
excluded_repositories = []
excluded_repositories = ["my-docker-local"]
create_archive = false
exclude_new_repositories = true
send_mail_on_error = true
verify_disk_space = true
export_mission_control = true
}
```
Note: `Key` argument has to match to the resource name.
Reference Link: [JFrog Artifactory Backup](https://www.jfrog.com/confluence/display/JFROG/Backups)

## Argument Reference
<!-- schema generated by tfplugindocs -->
## Schema

The following arguments are supported:
### Required

* `key` - (Required) The unique ID of the artifactory backup config.
* `enabled` - (Optional) Flag to enable or disable the backup config. Default value is `true`.
* `cron_exp` - (Required) A valid CRON expression that you can use to control backup frequency. Eg: "0 0 12 * * ? *", "0 0 2 ? * MON-SAT *". Note: please use 7 character format - Seconds, Minutes Hours, Day Of Month, Month, Day Of Week, Year. Also, specifying both a day-of-week AND a day-of-month parameter is not supported. One of them should be replaced by `?`. Incorrect: `* 5,7,9 14/2 * * WED,SAT *`, correct: `* 5,7,9 14/2 ? * WED,SAT *`. See details in [Cron Trigger Tutorial](http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) and in [Cronexp package readme](https://github.com/gorhill/cronexpr#other-details).
* `retention_period_hours` - (Optional) The number of hours to keep a backup before Artifactory will clean it up to free up disk space. Applicable only to non-incremental backups. Default value is 168 hours ie: 7 days.
* `excluded_repositories` - (Optional) A list of excluded repositories from the backup. Default is empty list.
* `create_archive` - (Optional) If set, backups will be created within a Zip archive (Slow and CPU intensive). Default value is `false`.
* `exclude_new_repositories` - (Optional) When set, new repositories will not be automatically added to the backup. Default value is `false`.
* `send_mail_on_error` - (Optional) If set, all Artifactory administrators will be notified by email if any problem is encountered during backup. Default value is `true`.
* `verify_disk_space` - (Optional) If set, Artifactory will verify that the backup target location has enough disk space available to hold the backed up data. If there is not enough space available, Artifactory will abort the backup and write a message in the log file. Applicable only to non-incremental backups.
* `export_mission_control` - (Optional) When set to true, mission control will not be automatically added to the backup. Default value is `false`.
- `cron_exp` (String) A valid CRON expression that you can use to control backup frequency. Eg: `0 0 12 * * ? *`, `0 0 2 ? * MON-SAT *`. **Note:** please use 7 character format - Seconds, Minutes Hours, Day Of Month, Month, Day Of Week, Year. Also, specifying both a day-of-week AND a day-of-month parameter is not supported. One of them should be replaced by `?`. Incorrect: `* 5,7,9 14/2 * * WED,SAT *`, correct: `* 5,7,9 14/2 ? * WED,SAT *`. See details in [Cron Trigger Tutorial](http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) and in [Cronexp package readme](https://github.com/gorhill/cronexpr#other-details).
- `key` (String)

### Optional

- `create_archive` (Boolean) If set to true, backups will be created within a Zip archive (Slow and CPU intensive). Default value is `false`
- `enabled` (Boolean) Flag to enable or disable the backup config. Default value is `true`.
- `exclude_new_repositories` (Boolean) When set to true, new repositories will not be automatically added to the backup. Default value is `false`.
- `excluded_repositories` (List of String) List of excluded repositories from the backup.
- `export_mission_control` (Boolean) When set to true, mission control will not be automatically added to the backup. Default value is `false`.
- `retention_period_hours` (Number) The number of hours to keep a backup before Artifactory will clean it up to free up disk space. Applicable only to non-incremental backups. Default value is 168 hours i.e. 7 days.
- `send_mail_on_error` (Boolean) If set to true, all Artifactory administrators will be notified by email if any problem is encountered during backup. Default value is `true`.
- `verify_disk_space` (Boolean) If set, Artifactory will verify that the backup target location has enough disk space available to hold the backed up data. If there is not enough space available, Artifactory will abort the backup and write a message in the log file. Applicable only to non-incremental backups. Default value is `false`.

## Import

Backup config can be imported using the key, e.g.
Import is supported using the following syntax:

```
$ terraform import artifactory_backup.backup_name backup_name
```shell
terraform import artifactory_backup.backup_name backup_name
```
1 change: 1 addition & 0 deletions examples/resources/artifactory_backup/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import artifactory_backup.backup_name backup_name
12 changes: 12 additions & 0 deletions examples/resources/artifactory_backup/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
resource "artifactory_backup" "backup_config_name" {
key = "backup_config_name"
enabled = true
cron_exp = "0 0 12 * * ? *"
retention_period_hours = 1000
excluded_repositories = ["my-docker-local"]
create_archive = false
exclude_new_repositories = true
send_mail_on_error = true
verify_disk_space = true
export_mission_control = true
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
Expand All @@ -24,16 +25,16 @@ import (
)

type BackupAPIModel struct {
Key string `xml:"key" yaml:"key"`
CronExp string `xml:"cronExp" yaml:"cronExp"`
Enabled bool `xml:"enabled" yaml:"enabled"`
RetentionPeriodHours int64 `xml:"retentionPeriodHours" yaml:"retentionPeriodHours"`
ExcludedRepositories *[]string `xml:"excludedRepositories>repositoryRef" yaml:"excludedRepositories"`
CreateArchive bool `xml:"createArchive" yaml:"createArchive"`
ExcludeNewRepositories bool `xml:"excludeNewRepositories" yaml:"excludeNewRepositories"`
SendMailOnError bool `xml:"sendMailOnError" yaml:"sendMailOnError"`
VerifyDiskSpace bool `xml:"precalculate" yaml:"precalculate"`
ExportMissionControl bool `xml:"exportMissionControl" yaml:"exportMissionControl"`
Key string `xml:"key" yaml:"key"`
CronExp string `xml:"cronExp" yaml:"cronExp"`
Enabled bool `xml:"enabled" yaml:"enabled"`
RetentionPeriodHours int64 `xml:"retentionPeriodHours" yaml:"retentionPeriodHours"`
ExcludedRepositories []string `xml:"excludedRepositories>repositoryRef" yaml:"excludedRepositories,omitempty"`
CreateArchive bool `xml:"createArchive" yaml:"createArchive"`
ExcludeNewRepositories bool `xml:"excludeNewRepositories" yaml:"excludeNewRepositories"`
SendMailOnError bool `xml:"sendMailOnError" yaml:"sendMailOnError"`
VerifyDiskSpace bool `xml:"precalculate" yaml:"precalculate"`
ExportMissionControl bool `xml:"exportMissionControl" yaml:"exportMissionControl"`
}

func (m BackupAPIModel) Id() string {
Expand All @@ -60,7 +61,7 @@ type BackupResourceModel struct {
func (r *BackupResourceModel) toAPIModel(ctx context.Context, backup *BackupAPIModel) diag.Diagnostics {
// Convert from Terraform resource model into API model
var excludedRepositories []string
diags := r.ExcludedRepositories.ElementsAs(ctx, &excludedRepositories, true)
diags := r.ExcludedRepositories.ElementsAs(ctx, &excludedRepositories, false)
if diags != nil {
return diags
}
Expand All @@ -73,15 +74,15 @@ func (r *BackupResourceModel) toAPIModel(ctx context.Context, backup *BackupAPIM
CreateArchive: r.CreateArchive.ValueBool(),
ExcludeNewRepositories: r.ExcludeNewRepositories.ValueBool(),
SendMailOnError: r.SendMailOnError.ValueBool(),
ExcludedRepositories: &excludedRepositories,
ExcludedRepositories: excludedRepositories,
VerifyDiskSpace: r.VerifyDiskSpace.ValueBool(),
ExportMissionControl: r.ExportMissionControl.ValueBool(),
}

return nil
}

func (r *BackupResourceModel) FromAPIModel(ctx context.Context, backup *BackupAPIModel) diag.Diagnostics {
func (r *BackupResourceModel) fromAPIModel(ctx context.Context, backup *BackupAPIModel) diag.Diagnostics {
r.Key = types.StringValue(backup.Key)
r.Enabled = types.BoolValue(backup.Enabled)
r.CronExp = types.StringValue(backup.CronExp)
Expand All @@ -94,6 +95,7 @@ func (r *BackupResourceModel) FromAPIModel(ctx context.Context, backup *BackupAP
if diags != nil {
return diags
}

r.ExcludedRepositories = excludedRepositories
r.VerifyDiskSpace = types.BoolValue(backup.VerifyDiskSpace)
r.ExportMissionControl = types.BoolValue(backup.ExportMissionControl)
Expand All @@ -118,7 +120,6 @@ func (r *BackupResource) Metadata(ctx context.Context, req resource.MetadataRequ

func (r *BackupResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: "Provides an Artifactory backup config resource. This resource configuration corresponds to backup config block in system configuration XML (REST endpoint: artifactory/api/system/configuration). Manages the automatic and periodic backups of the entire Artifactory instance.",
Attributes: map[string]schema.Attribute{
"key": schema.StringAttribute{
Required: true,
Expand Down Expand Up @@ -152,9 +153,12 @@ func (r *BackupResource) Schema(ctx context.Context, req resource.SchemaRequest,
},
},
"excluded_repositories": schema.ListAttribute{
MarkdownDescription: "List of excluded repositories from the backup. Default is empty list.",
MarkdownDescription: "List of excluded repositories from the backup.",
Optional: true,
ElementType: types.StringType,
Validators: []validator.List{
listvalidator.SizeAtLeast(1),
},
},
"create_archive": schema.BoolAttribute{
MarkdownDescription: "If set to true, backups will be created within a Zip archive (Slow and CPU intensive). Default value is `false`",
Expand Down Expand Up @@ -187,6 +191,7 @@ func (r *BackupResource) Schema(ctx context.Context, req resource.SchemaRequest,
Default: booldefault.StaticBool(false),
},
},
MarkdownDescription: "This resource can be used to manage the automatic and periodic backups of the entire Artifactory instance.\n\nWhen an `artifactory_backup` resource is configured and enabled to true, backup of the entire Artifactory system will be done automatically and periodically.\n\nThe backup process creates a time-stamped directory in the target backup directory.\n\nSee [JFrog Artifactory Backup](https://www.jfrog.com/confluence/display/JFROG/Backups) for more details.\n\n~>Only supported in self-hosted environment.",
}
}

Expand Down Expand Up @@ -282,7 +287,7 @@ func (r *BackupResource) Read(ctx context.Context, req resource.ReadRequest, res

// Convert from the API data model to the Terraform data model
// and refresh any attribute values.
resp.Diagnostics.Append(state.FromAPIModel(ctx, matchedBackup)...)
resp.Diagnostics.Append(state.fromAPIModel(ctx, matchedBackup)...)
if resp.Diagnostics.HasError() {
return
}
Expand Down Expand Up @@ -331,7 +336,7 @@ func (r *BackupResource) Update(ctx context.Context, req resource.UpdateRequest,
return
}

resp.Diagnostics.Append(data.FromAPIModel(ctx, &backup)...)
resp.Diagnostics.Append(data.fromAPIModel(ctx, &backup)...)
if resp.Diagnostics.HasError() {
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ resource "artifactory_backup" "{{ .resourceName }}" {
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(fqrn, "enabled", "true"),
resource.TestCheckResourceAttr(fqrn, "cron_exp", "0 0 2 ? * MON-SAT *"),
resource.TestCheckResourceAttr(fqrn, "excluded_repositories.#", "0"),
),
},
{
Expand Down
2 changes: 1 addition & 1 deletion scripts/run-artifactory-container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
source "${SCRIPT_DIR}/get-access-key.sh"
source "${SCRIPT_DIR}/wait-for-rt.sh"

export ARTIFACTORY_VERSION=${ARTIFACTORY_VERSION:-7.90.8}
export ARTIFACTORY_VERSION=${ARTIFACTORY_VERSION:-7.98.10}
echo "ARTIFACTORY_VERSION=${ARTIFACTORY_VERSION}" > /dev/stderr

set -euf
Expand Down
2 changes: 1 addition & 1 deletion scripts/run-artifactory.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
source "${SCRIPT_DIR}/get-access-key.sh"
source "${SCRIPT_DIR}/wait-for-rt.sh"
export ARTIFACTORY_VERSION=${ARTIFACTORY_VERSION:-7.90.8}
export ARTIFACTORY_VERSION=${ARTIFACTORY_VERSION:-7.98.10}
echo "ARTIFACTORY_VERSION=${ARTIFACTORY_VERSION}"

set -euf
Expand Down
Loading