diff --git a/internal/provider/main.go b/internal/provider/main.go index 0b0b70e3..ef956b19 100755 --- a/internal/provider/main.go +++ b/internal/provider/main.go @@ -4,6 +4,7 @@ import ( nexus "github.com/datadrivers/go-nexus-client/nexus3" "github.com/datadrivers/go-nexus-client/nexus3/pkg/client" "github.com/datadrivers/terraform-provider-nexus/internal/services/blobstore" + "github.com/datadrivers/terraform-provider-nexus/internal/services/cleanuppolicies" "github.com/datadrivers/terraform-provider-nexus/internal/services/other" "github.com/datadrivers/terraform-provider-nexus/internal/services/repository" "github.com/datadrivers/terraform-provider-nexus/internal/services/security" @@ -79,6 +80,7 @@ func Provider() *schema.Provider { "nexus_privilege_repository_view": security.DataSourceSecurityPrivilegeRepositoryView(), "nexus_privilege_repository_admin": security.DataSourceSecurityPrivilegeRepositoryAdmin(), "nexus_privilege_repository_content_selector": security.DataSourceSecurityPrivilegeRepositoryContentSelector(), + "nexus_cleanup_policy": cleanuppolicies.DataSourceRepositoryCleanupPolicies(), }, ResourcesMap: map[string]*schema.Resource{ "nexus_blobstore_azure": blobstore.ResourceBlobstoreAzure(), @@ -145,6 +147,7 @@ func Provider() *schema.Provider { "nexus_privilege_repository_admin": security.ResourceSecurityPrivilegeRepositoryAdmin(), "nexus_privilege_repository_content_selector": security.ResourceSecurityPrivilegeRepositoryContentSelector(), "nexus_privilege_wildcard": security.ResourceSecurityPrivilegeWildcard(), + "nexus_cleanup_policy": cleanuppolicies.ResourceCleanupPolicies(), }, Schema: map[string]*schema.Schema{ "insecure": { diff --git a/internal/services/cleanuppolicies/data_source_cleanup_policies.go b/internal/services/cleanuppolicies/data_source_cleanup_policies.go new file mode 100644 index 00000000..4ccadb41 --- /dev/null +++ b/internal/services/cleanuppolicies/data_source_cleanup_policies.go @@ -0,0 +1,60 @@ +package cleanuppolicies + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func DataSourceRepositoryCleanupPolicies() *schema.Resource { + return &schema.Resource{ + Description: "Manages a cleanup policy in Nexus Repository.", + + Read: dataSourceRepositoryCleanupPoliciesRead, + + Schema: map[string]*schema.Schema{ + "notes": { + Description: "Any details on the specific cleanup policy", + Type: schema.TypeString, + Computed: true, + }, + "criteria_last_blob_updated": { + Description: "The age of the component in days", + Type: schema.TypeInt, + Computed: true, + }, + "criteria_last_downloaded": { + Description: "the last time the component had been downloaded in days", + Type: schema.TypeInt, + Computed: true, + }, + "criteria_release_type": { + Description: "When needed, this is either PRELEASE or RELEASE", + Type: schema.TypeString, + Computed: true, + }, + "criteria_asset_regex": { + Description: "A regex string to filter for specific asset paths", + Type: schema.TypeString, + Computed: true, + }, + "retain": { + Description: "Number of versions to keep. Only available for Docker and Maven release repositories on PostgreSQL deployments", + Type: schema.TypeInt, + Required: true, + }, + "name": { + Description: "The name of the policy needs to be unique and cannot be edited once set. Only letters, digits, underscores(_), hyphens(-), and dots(.) are allowed and may not start with underscore or dot", + Type: schema.TypeString, + Required: true, + }, + "format": { + Description: "The target format for the cleanup policy. Some formats have various capabilities and requirements. Note that you cannot currently specify all formats", + Type: schema.TypeString, + Required: true, + }, + }, + } +} + +func dataSourceRepositoryCleanupPoliciesRead(d *schema.ResourceData, m interface{}) error { + return resourceCleanupPoliciesRead(d, m) +} diff --git a/internal/services/cleanuppolicies/data_source_cleanup_policies_test.go b/internal/services/cleanuppolicies/data_source_cleanup_policies_test.go new file mode 100644 index 00000000..368d734b --- /dev/null +++ b/internal/services/cleanuppolicies/data_source_cleanup_policies_test.go @@ -0,0 +1,55 @@ +package cleanuppolicies_test + +import ( + "github.com/datadrivers/go-nexus-client/nexus3/schema/cleanuppolicies" + "strconv" + "testing" + + "github.com/datadrivers/go-nexus-client/nexus3/pkg/tools" + "github.com/datadrivers/terraform-provider-nexus/internal/acceptance" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccDataSourceCleanupPolicy(t *testing.T) { + dataSourceName := "data.nexus_cleanup_policy.acceptance" + + cp := cleanuppolicies.CleanupPolicy{ + Notes: tools.GetStringPointer(acctest.RandString(25)), + CriteriaLastBlobUpdated: tools.GetIntPointer(acctest.RandInt()), + CriteriaLastDownloaded: tools.GetIntPointer(acctest.RandInt()), + CriteriaReleaseType: tools.GetStringPointer(acctest.RandString(8)), + CriteriaAssetRegex: tools.GetStringPointer(acctest.RandString(15)), + Retain: acctest.RandInt(), + Name: acctest.RandString(10), + Format: acctest.RandString(5), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.AccPreCheck(t) }, + Providers: acceptance.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccResourceCleanupPolicyConfig(cp) + testAccDataSourceCleanupPolicyConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPtr(dataSourceName, "notes", cp.Notes), + resource.TestCheckResourceAttr(dataSourceName, "criteria_last_blob_updated", strconv.Itoa(*cp.CriteriaLastBlobUpdated)), + resource.TestCheckResourceAttr(dataSourceName, "criteria_last_downloaded", strconv.Itoa(*cp.CriteriaLastDownloaded)), + resource.TestCheckResourceAttrPtr(dataSourceName, "criteria_release_type", cp.CriteriaReleaseType), + resource.TestCheckResourceAttrPtr(dataSourceName, "criteria_asset_regex", cp.CriteriaAssetRegex), + resource.TestCheckResourceAttr(dataSourceName, "retain", strconv.Itoa(cp.Retain)), + resource.TestCheckResourceAttr(dataSourceName, "name", cp.Name), + resource.TestCheckResourceAttr(dataSourceName, "format", cp.Format), + ), + }, + }, + }) +} + +func testAccDataSourceCleanupPolicyConfig() string { + return ` +data "nexus_cleanup_policy" "acceptance" { + name = nexus_cleanup_policy.acceptance.name +} +` +} diff --git a/internal/services/cleanuppolicies/resource_cleanup_policies.go b/internal/services/cleanuppolicies/resource_cleanup_policies.go new file mode 100644 index 00000000..c699ec21 --- /dev/null +++ b/internal/services/cleanuppolicies/resource_cleanup_policies.go @@ -0,0 +1,175 @@ +package cleanuppolicies + +import ( + nexus "github.com/datadrivers/go-nexus-client/nexus3" + "github.com/datadrivers/go-nexus-client/nexus3/schema/cleanuppolicies" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func ResourceCleanupPolicies() *schema.Resource { + return &schema.Resource{ + Description: "Manages a cleanup policy in Nexus Repository.", + + Create: resourceCleanupPoliciesCreate, + Read: resourceCleanupPoliciesRead, + Update: resourceCleanupPoliciesUpdate, + Delete: resourceCleanupPoliciesDelete, + Exists: resourceCleanupPoliciesExists, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + "notes": { + Description: "Any details on the specific cleanup policy", + Type: schema.TypeString, + Optional: true, + }, + "criteria_last_blob_updated": { + Description: "The age of the component in days", + Type: schema.TypeInt, + Optional: true, + Default: nil, + }, + "criteria_last_downloaded": { + Description: "the last time the component had been downloaded in days", + Type: schema.TypeInt, + Optional: true, + Default: nil, + }, + "criteria_release_type": { + Description: "When needed, this is either PRELEASE or RELEASE", + Type: schema.TypeString, + Optional: true, + Default: nil, + }, + "criteria_asset_regex": { + Description: "A regex string to filter for specific asset paths", + Type: schema.TypeString, + Optional: true, + Default: nil, + }, + "retain": { + Description: "Number of versions to keep. Only available for Docker and Maven release repositories on PostgreSQL deployments", + Type: schema.TypeInt, + Optional: true, + Default: 1, + }, + "name": { + Description: "The name of the policy needs to be unique and cannot be edited once set. Only letters, digits, underscores(_), hyphens(-), and dots(.) are allowed and may not start with underscore or dot", + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "format": { + Description: "The target format for the cleanup policy. Some formats have various capabilities and requirements. Note that you cannot currently specify all formats", + Type: schema.TypeString, + Required: true, + }, + }, + } +} + +func getCleanupPolicyFromResourceData(d *schema.ResourceData) cleanuppolicies.CleanupPolicy { + + notes, _ := d.Get("notes").(string) + criteriaLastBlobUpdated, _ := d.Get("criteria_last_blob_updated").(int) + criteriaLastDownloaded, _ := d.Get("criteria_last_downloaded").(int) + criteriaReleaseType, _ := d.Get("criteria_release_type").(string) + criteriaAssetRegex, _ := d.Get("criteria_asset_regex").(string) + retain, _ := d.Get("retain").(int) + name, _ := d.Get("name").(string) + format, _ := d.Get("format").(string) + + policy := cleanuppolicies.CleanupPolicy{ + Notes: ¬es, + CriteriaLastBlobUpdated: &criteriaLastBlobUpdated, + CriteriaLastDownloaded: &criteriaLastDownloaded, + CriteriaAssetRegex: &criteriaAssetRegex, + Name: name, + Format: format, + } + + // Only set CriteriaReleaseType for applicable formats + if format == "maven2" || format == "npm" || format == "yum" { + policy.CriteriaReleaseType = &criteriaReleaseType + } + + // Only set CriteriaReleaseType for applicable formats + if format == "maven2" || format == "docker" { + policy.Retain = retain + } + + return policy +} + +func setCleanupPolicyToResourceData(cleanupPolicy *cleanuppolicies.CleanupPolicy, d *schema.ResourceData) error { + d.SetId(cleanupPolicy.Name) + d.Set("notes", cleanupPolicy.Notes) + d.Set("criteria_last_blob_updated", cleanupPolicy.CriteriaLastBlobUpdated) + d.Set("criteria_last_downloaded", cleanupPolicy.CriteriaLastDownloaded) + d.Set("criteria_release_type", cleanupPolicy.CriteriaReleaseType) + d.Set("criteria_asset_regex", cleanupPolicy.CriteriaAssetRegex) + d.Set("retain", cleanupPolicy.Retain) + d.Set("name", cleanupPolicy.Name) + d.Set("format", cleanupPolicy.Format) + return nil +} + +func resourceCleanupPoliciesCreate(d *schema.ResourceData, m interface{}) error { + client := m.(*nexus.NexusClient) + + cleanupPolicy := getCleanupPolicyFromResourceData(d) + + if err := client.CleanupPolicy.Create(&cleanupPolicy); err != nil { + return err + } + + d.SetId(cleanupPolicy.Name) + + return resourceCleanupPoliciesRead(d, m) +} + +func resourceCleanupPoliciesRead(d *schema.ResourceData, m interface{}) error { + client := m.(*nexus.NexusClient) + + cleanupPolicy, err := client.CleanupPolicy.Get(d.Id()) + if err != nil { + return err + } + + if cleanupPolicy == nil { + d.SetId("") + return nil + } + + return setCleanupPolicyToResourceData(cleanupPolicy, d) +} + +func resourceCleanupPoliciesUpdate(d *schema.ResourceData, m interface{}) error { + client := m.(*nexus.NexusClient) + + cleanupPolicy := getCleanupPolicyFromResourceData(d) + if err := client.CleanupPolicy.Update(&cleanupPolicy); err != nil { + return err + } + + return resourceCleanupPoliciesRead(d, m) +} + +func resourceCleanupPoliciesDelete(d *schema.ResourceData, m interface{}) error { + client := m.(*nexus.NexusClient) + + if err := client.CleanupPolicy.Delete(d.Id()); err != nil { + return err + } + + d.SetId("") + return nil +} + +func resourceCleanupPoliciesExists(d *schema.ResourceData, m interface{}) (bool, error) { + client := m.(*nexus.NexusClient) + + cleanupPolicy, err := client.CleanupPolicy.Get(d.Id()) + return cleanupPolicy != nil, err +} diff --git a/internal/services/cleanuppolicies/resource_cleanup_policies_test.go b/internal/services/cleanuppolicies/resource_cleanup_policies_test.go new file mode 100644 index 00000000..bd341490 --- /dev/null +++ b/internal/services/cleanuppolicies/resource_cleanup_policies_test.go @@ -0,0 +1,71 @@ +package cleanuppolicies_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/datadrivers/go-nexus-client/nexus3/pkg/tools" + "github.com/datadrivers/go-nexus-client/nexus3/schema/cleanuppolicies" + "github.com/datadrivers/terraform-provider-nexus/internal/acceptance" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccResourceCleanupPolicy(t *testing.T) { + var cleanupPolicy cleanuppolicies.CleanupPolicy + + resName := "nexus_security_cleanup_policy.acceptance" + cp := cleanuppolicies.CleanupPolicy{ + Notes: tools.GetStringPointer(acctest.RandString(25)), + CriteriaLastBlobUpdated: tools.GetIntPointer(acctest.RandInt()), + CriteriaLastDownloaded: tools.GetIntPointer(acctest.RandInt()), + CriteriaReleaseType: tools.GetStringPointer(acctest.RandString(8)), + CriteriaAssetRegex: tools.GetStringPointer(acctest.RandString(15)), + Retain: acctest.RandInt(), + Name: acctest.RandString(10), + Format: acctest.RandString(5), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.AccPreCheck(t) }, + Providers: acceptance.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccResourceCleanupPolicyConfig(cp) + testAccDataSourceCleanupPolicyConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resName, "notes", *cp.Notes), + resource.TestCheckResourceAttr(resName, "criteria_last_blob_updated", strconv.Itoa(*cp.CriteriaLastBlobUpdated)), + resource.TestCheckResourceAttr(resName, "criteria_last_downloaded", strconv.Itoa(*cp.CriteriaLastDownloaded)), + resource.TestCheckResourceAttr(resName, "criteria_release_type", *cp.CriteriaReleaseType), + resource.TestCheckResourceAttr(resName, "criteria_asset_regex", *cp.CriteriaAssetRegex), + resource.TestCheckResourceAttr(resName, "retain", strconv.Itoa(cp.Retain)), + resource.TestCheckResourceAttr(resName, "name", cp.Name), + resource.TestCheckResourceAttr(resName, "format", cp.Format), + ), + }, + { + ResourceName: resName, + ImportStateId: cleanupPolicy.Name, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccResourceCleanupPolicyConfig(cp cleanuppolicies.CleanupPolicy) string { + return fmt.Sprintf(` +resource "nexus_security_cleanup_policy" "acceptance" { + notes = "%s" + criteria_last_blob_updated = "%s" + criteria_last_downloaded = "%s" + criteria_release_type = "%s" + criteria_asset_regex = "%s" + retain = "%s" + name = "%s" + format = "%s" +} +`, *cp.Notes, strconv.Itoa(*cp.CriteriaLastBlobUpdated), strconv.Itoa(*cp.CriteriaLastDownloaded), + *cp.CriteriaReleaseType, *cp.CriteriaAssetRegex, strconv.Itoa(cp.Retain), cp.Name, cp.Format) +}