diff --git a/nexus3/pkg/cleanup/service.go b/nexus3/pkg/cleanup/service.go new file mode 100644 index 0000000..e2f009d --- /dev/null +++ b/nexus3/pkg/cleanup/service.go @@ -0,0 +1,95 @@ +package cleanup + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/datadrivers/go-nexus-client/nexus3/pkg/client" + "github.com/datadrivers/go-nexus-client/nexus3/pkg/tools" + "github.com/datadrivers/go-nexus-client/nexus3/schema/cleanuppolicies" +) + +const ( + cleanupAPIEndpoint = client.BasePath + "v1/cleanup-policies" +) + +type CleanupPolicyService client.Service + +func NewCleanupPolicyService(c *client.Client) *CleanupPolicyService { + return &CleanupPolicyService{Client: c} +} + +func (s *CleanupPolicyService) Create(policy *cleanuppolicies.CleanupPolicy) error { + data, err := tools.JsonMarshalInterfaceToIOReader(policy) + if err != nil { + return err + } + body, resp, err := s.Client.Post(cleanupAPIEndpoint, data) + if err != nil { + return err + } + if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { + return fmt.Errorf("could not create cleanup policy '%s': HTTP: %d, %s", policy.Name, resp.StatusCode, string(body)) + } + return nil +} + +func (s *CleanupPolicyService) Get(name string) (*cleanuppolicies.CleanupPolicy, error) { + + body, resp, err := s.Client.Get(fmt.Sprintf("%s/%s", cleanupAPIEndpoint, name), nil) + if err != nil { + return nil, err + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("could not get cleanup policy '%s': HTTP: %d, %s", name, resp.StatusCode, string(body)) + } + policy := &cleanuppolicies.CleanupPolicy{} + if err := json.Unmarshal(body, policy); err != nil { + return nil, fmt.Errorf("could not unmarshal repository: %v", err) + } + + return policy, nil +} + +func (s *CleanupPolicyService) Update(policy *cleanuppolicies.CleanupPolicy) error { + data, err := tools.JsonMarshalInterfaceToIOReader(policy) + if err != nil { + return err + } + body, resp, err := s.Client.Put(fmt.Sprintf("%s/%s", cleanupAPIEndpoint, policy.Name), data) + if err != nil { + return err + } + if resp.StatusCode != http.StatusNoContent { + return fmt.Errorf("could not update cleanup policy '%s': HTTP: %d, %s", policy.Name, resp.StatusCode, string(body)) + } + return nil +} + +func (s *CleanupPolicyService) Delete(name string) error { + endpoint := cleanupAPIEndpoint + "/" + name + body, resp, err := s.Client.Delete(endpoint) + if err != nil { + return err + } + if resp.StatusCode != http.StatusNoContent { + return fmt.Errorf("could not delete cleanup policy '%s': HTTP: %d, %s", name, resp.StatusCode, string(body)) + } + return nil +} + +func (s *CleanupPolicyService) List() ([]*cleanuppolicies.CleanupPolicy, error) { + body, resp, err := s.Client.Get(cleanupAPIEndpoint, nil) + if err != nil { + return nil, err + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("could not list cleanup policies: HTTP: %d, %s", resp.StatusCode, string(body)) + } + var policies []*cleanuppolicies.CleanupPolicy + if err := json.Unmarshal(body, &policies); err != nil { + return nil, fmt.Errorf("could not unmarshal cleanup policies: %v", err) + } + return policies, nil +} diff --git a/nexus3/pkg/cleanup/service_test.go b/nexus3/pkg/cleanup/service_test.go new file mode 100644 index 0000000..a2cc41b --- /dev/null +++ b/nexus3/pkg/cleanup/service_test.go @@ -0,0 +1,86 @@ +package cleanup_test + +import ( + "testing" + + "github.com/datadrivers/go-nexus-client/nexus3/pkg/cleanup" + "github.com/datadrivers/go-nexus-client/nexus3/pkg/client" + "github.com/datadrivers/go-nexus-client/nexus3/pkg/tools" + "github.com/datadrivers/go-nexus-client/nexus3/schema/cleanuppolicies" + "github.com/stretchr/testify/assert" +) + +// https://help.sonatype.com/en/cleanup-policies-api.html + +var ( + testClient *client.Client = nil +) + +func getTestClient() *client.Client { + if testClient != nil { + return testClient + } + return client.NewClient(getDefaultConfig()) +} + +func getTestService() *cleanup.CleanupPolicyService { + return cleanup.NewCleanupPolicyService(getTestClient()) +} + +func getDefaultConfig() client.Config { + return client.Config{ + Insecure: tools.GetEnv("NEXUS_INSECURE_SKIP_VERIFY", true).(bool), + Password: tools.GetEnv("NEXUS_PASSWORD", "admin123").(string), + URL: tools.GetEnv("NEXUS_URL", "http://127.0.0.1:8081").(string), + Username: tools.GetEnv("NEXUS_USRNAME", "admin").(string), + } +} + +func TestNewCleanupService(t *testing.T) { + s := getTestService() + + assert.NotNil(t, s, "NewCleanupService() must not return nil") +} + +func TestCreateCleanupPolicy(t *testing.T) { + s := getTestService() + + policy := &cleanuppolicies.CleanupPolicy{ + Notes: tools.GetStringPointer("Test"), + CriteriaAssetRegex: tools.GetStringPointer("*"), + Name: "Test", + Format: cleanuppolicies.FormatGo, + } + + policy2 := &cleanuppolicies.CleanupPolicy{ + Notes: tools.GetStringPointer("Test2"), + CriteriaAssetRegex: tools.GetStringPointer("*"), + Name: "Test2", + Format: cleanuppolicies.FormatApt, + } + + err := s.Create(policy) + assert.Nil(t, err, "Create() must not return an error") + + err = s.Create(policy2) + assert.Nil(t, err, "Second Create() must not return an error") + + policy, err = s.Get(policy.Name) + assert.Nil(t, err, "Get() must not return an error") + assert.Equal(t, policy.Name, "Test") + + policies, err := s.List() + assert.Nil(t, err, "List() must not return an error") + assert.Equal(t, len(policies), 2) + + policy.CriteriaLastBlobUpdated = tools.GetIntPointer(1) + err = s.Update(policy) + assert.Nil(t, err, "Update() must not return an error") + assert.Equal(t, policy.CriteriaLastBlobUpdated, tools.GetIntPointer(1)) + + err = s.Delete(policy.Name) + assert.Nil(t, err, "Delete() must not return an error") + + err = s.Delete(policy2.Name) + assert.Nil(t, err, "Second Delete() must not return an error") +} diff --git a/nexus3/schema/cleanuppolicies/cleanup-policies.go b/nexus3/schema/cleanuppolicies/cleanup-policies.go new file mode 100644 index 0000000..ac016b6 --- /dev/null +++ b/nexus3/schema/cleanuppolicies/cleanup-policies.go @@ -0,0 +1,42 @@ +package cleanuppolicies + +type RepositoryFormat string +type CriteriaReleaseType string + +const ( + FormatAny RepositoryFormat = "*" + FormatApt RepositoryFormat = "apt" + FormatBower RepositoryFormat = "bower" + FormatCocoapods RepositoryFormat = "cocoapods" + FormatConan RepositoryFormat = "conan" + FormatConda RepositoryFormat = "conda" + FormatDocker RepositoryFormat = "docker" + FormatGo RepositoryFormat = "go" + FormatHelm RepositoryFormat = "helm" + FormatMaven RepositoryFormat = "maven" + FormatNpm RepositoryFormat = "npm" + FormatNuget RepositoryFormat = "nuget" + FormatPypi RepositoryFormat = "pypi" + FormatR RepositoryFormat = "r" + FormatRaw RepositoryFormat = "raw" + FormatRubyGems RepositoryFormat = "rubygems" + FormatTerraform RepositoryFormat = "terraform" + FormatYum RepositoryFormat = "yum" +) + +const ( + CriteriaReleaseTypeReleasesAndPrereleases CriteriaReleaseType = "RELEASES_AND_PRERELEASES" + CriteriaReleaseTypePrereleases CriteriaReleaseType = "PRERELEASES" + CriteriaReleaseTypeReleases CriteriaReleaseType = "RELEASES" +) + +type CleanupPolicy struct { + Notes *string `json:"notes,omitempty"` // any details on the specific cleanup policy. + CriteriaLastBlobUpdated *int `json:"criteriaLastBlobUpdated,omitempty"` // the age of the component in days. + CriteriaLastDownloaded *int `json:"criteriaLastDownloaded,omitempty"` // the last time the component had been downloaded in days. + CriteriaReleaseType *CriteriaReleaseType `json:"criteriaReleaseType,omitempty"` // is one of: RELEASES_AND_PRERELEASES, PRERELEASES, RELEASES], Only maven2, npm and yum repositories support this field. + CriteriaAssetRegex *string `json:"criteriaAssetRegex,omitempty"` // a regex string to filter for specific asset paths. Not for gitlfs or * + Retain int `json:"retain,omitempty"` // number of versions to keep. Only available for Docker and Maven release repositories on PostgreSQL deployments. + Name string `json:"name"` // 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. + Format RepositoryFormat `json:"format"` // one of ["*", "apt", "bower", "cocoapods", "conan", "conda", "docker", "gitlfs", "go", "helm", "maven2", "npm", "nuget", "p2", "pypi", "r", "raw", "rubygems", "yum"] +}