Skip to content
Open
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

BUG FIXES:

* resource/xray_settings: Make `db_sync_updates_time` attribute optional so users can configure Artifactory/Xray integration settings without being forced to specify the internal DB sync schedule. When omitted, the provider preserves the existing server value. Issue: [#425](https://github.com/jfrog/terraform-provider-xray/issues/425) PR: [#426](https://github.com/jfrog/terraform-provider-xray/pull/426)

* resource/xray_curation_policy: Fix false `Decision owners required` validation error when `decision_owners` is sourced from another resource, module variable, or other value that is unknown until apply, while `waiver_request_config = "manual"`. The `decisionOwnersRequiredValidator` now skips unknown values and defers validation to the plan phase. Issue: [#433](https://github.com/jfrog/terraform-provider-xray/issues/433)

* resource/xray_curation_policy: Add `block_from_cache` attribute so the "Enforce policy on cached packages" setting is read from and written to the API instead of being silently reset to `false` on every update. Issue: [#431](https://github.com/jfrog/terraform-provider-xray/issues/431) PR: [#435](https://github.com/jfrog/terraform-provider-xray/pull/435)
Expand Down
65 changes: 52 additions & 13 deletions pkg/xray/resource/resource_xray_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package xray

import (
"context"
"errors"
"fmt"
"regexp"

"github.com/go-resty/resty/v2"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
Expand Down Expand Up @@ -76,6 +78,21 @@ type DbSyncDailyUpdatesTimeErrorAPIModel struct {
Error string `json:"error"`
}

func readDBSyncUpdateTime(request *resty.Request) (string, error) {
var dbSyncTime DbSyncDailyUpdatesTimeAPIModel
response, err := request.
SetResult(&dbSyncTime).
Get(DBSyncEndPoint)
if err != nil {
return "", err
}
if response.IsError() {
return "", errors.New(response.String())
}

return dbSyncTime.DbSyncTime, nil
}

func (r *SettingsResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
Expand All @@ -86,11 +103,12 @@ func (r *SettingsResource) Schema(ctx context.Context, req resource.SchemaReques
},
},
"db_sync_updates_time": schema.StringAttribute{
Required: true,
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.RegexMatches(regexp.MustCompile(`^([0-1][0-9]|[2][0-3]):([0-5][0-9])$`), "Wrong format input, expected valid hour:minutes (HH:mm) form"),
},
Description: "The time of the Xray DB sync daily update job. Format `HH:mm`",
Description: "The time of the Xray DB sync daily update job. Format `HH:mm`. If not set, the existing server value is preserved.",
},
"enabled": schema.BoolAttribute{
Optional: true,
Expand Down Expand Up @@ -167,6 +185,20 @@ func (r *SettingsResource) Create(ctx context.Context, req resource.CreateReques
return
}

// If db_sync_updates_time is not in config, read the current server value
// so the Computed attribute is populated in state.
if plan.DBSyncUpdateTime.IsNull() || plan.DBSyncUpdateTime.IsUnknown() {
currentDbSyncTime, err := readDBSyncUpdateTime(request)
if err != nil {
utilfw.UnableToCreateResourceError(resp, err.Error())
return
}
plan.DBSyncUpdateTime = types.StringValue(currentDbSyncTime)
plan.ID = types.StringValue("settings")
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
return
}

dbSyncTime := DbSyncDailyUpdatesTimeAPIModel{
DbSyncTime: plan.DBSyncUpdateTime.ValueString(),
}
Expand All @@ -184,7 +216,7 @@ func (r *SettingsResource) Create(ctx context.Context, req resource.CreateReques
return
}

plan.ID = types.StringValue(dbSyncTime.DbSyncTime)
plan.ID = types.StringValue("settings")

// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
Expand Down Expand Up @@ -223,20 +255,13 @@ func (r *SettingsResource) Read(ctx context.Context, req resource.ReadRequest, r
state.BlockUnfinishedScansTimeout = types.Int64Value(settings.BlockUnfinishedScansTimeout)
state.BlockUnscannedTimeout = types.Int64Value(settings.BlockUnscannedTimeout)

var dbSyncTime DbSyncDailyUpdatesTimeAPIModel
response, err = request.
SetResult(&dbSyncTime).
Get(DBSyncEndPoint)
dbSyncTime, err := readDBSyncUpdateTime(request)
if err != nil {
utilfw.UnableToRefreshResourceError(resp, fmt.Sprintf("failed to retrieve data from API during Read: %s", err.Error()))
return
}
if response.IsError() {
utilfw.UnableToRefreshResourceError(resp, fmt.Sprintf("failed to retrieve data from API during Read: %s", response.String()))
return
}

state.DBSyncUpdateTime = types.StringValue(dbSyncTime.DbSyncTime)
state.DBSyncUpdateTime = types.StringValue(dbSyncTime)

// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, state)...)
Expand Down Expand Up @@ -274,6 +299,20 @@ func (r *SettingsResource) Update(ctx context.Context, req resource.UpdateReques
return
}

// If db_sync_updates_time is not in config, read the current server value
Comment thread
System-Arch marked this conversation as resolved.
// so the Computed attribute is populated in state.
if plan.DBSyncUpdateTime.IsNull() || plan.DBSyncUpdateTime.IsUnknown() {
currentDbSyncTime, err := readDBSyncUpdateTime(request)
if err != nil {
utilfw.UnableToUpdateResourceError(resp, err.Error())
return
}
plan.DBSyncUpdateTime = types.StringValue(currentDbSyncTime)
plan.ID = types.StringValue("settings")
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
return
}

dbSyncTime := DbSyncDailyUpdatesTimeAPIModel{
DbSyncTime: plan.DBSyncUpdateTime.ValueString(),
}
Expand All @@ -289,7 +328,7 @@ func (r *SettingsResource) Update(ctx context.Context, req resource.UpdateReques
return
}

plan.ID = types.StringValue(dbSyncTime.DbSyncTime)
plan.ID = types.StringValue("settings")

// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
Expand Down
53 changes: 53 additions & 0 deletions pkg/xray/resource/resource_xray_settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,59 @@ func TestAccSettings_basic(t *testing.T) {
})
}

func TestAccSettings_noDbSyncTime(t *testing.T) {
Comment thread
System-Arch marked this conversation as resolved.
_, fqrn, resourceName := testutil.MkNames("test-settings", "xray_settings")

tmpl := `
resource "xray_settings" "{{ .name }}" {
enabled = true
allow_blocked = {{ .allowBlocked }}
allow_when_unavailable = {{ .allowWhenUnavailable }}
block_unscanned_timeout = {{ .blockUnscannedTimeout }}
block_unfinished_scans_timeout = {{ .blockUnfinishedScansTimeout }}
}`

testData := map[string]any{
"name": resourceName,
"allowBlocked": testutil.RandBool(),
"allowWhenUnavailable": testutil.RandBool(),
"blockUnscannedTimeout": 120,
"blockUnfinishedScansTimeout": 3600,
}

config := util.ExecuteTemplate(fqrn, tmpl, testData)

resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(fqrn, "enabled", "true"),
resource.TestCheckResourceAttr(fqrn, "allow_blocked", fmt.Sprintf("%t", testData["allowBlocked"])),
resource.TestCheckResourceAttr(fqrn, "allow_when_unavailable", fmt.Sprintf("%t", testData["allowWhenUnavailable"])),
resource.TestCheckResourceAttr(fqrn, "block_unscanned_timeout", fmt.Sprintf("%d", testData["blockUnscannedTimeout"])),
resource.TestCheckResourceAttr(fqrn, "block_unfinished_scans_timeout", fmt.Sprintf("%d", testData["blockUnfinishedScansTimeout"])),
resource.TestCheckResourceAttrSet(fqrn, "db_sync_updates_time"),
),
},
{
Config: config,
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectEmptyPlan(),
},
},
},
{
ResourceName: fqrn,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccSettings_DbSyncTime(t *testing.T) {
_, fqrn, resourceName := testutil.MkNames("db_sync-", "xray_settings")
time := "18:45"
Expand Down
Loading