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

feat: add support for cleanup policies #152

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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
95 changes: 95 additions & 0 deletions nexus3/pkg/cleanup/service.go
Original file line number Diff line number Diff line change
@@ -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
}
86 changes: 86 additions & 0 deletions nexus3/pkg/cleanup/service_test.go
Original file line number Diff line number Diff line change
@@ -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")
}
42 changes: 42 additions & 0 deletions nexus3/schema/cleanuppolicies/cleanup-policies.go
Original file line number Diff line number Diff line change
@@ -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"]
}