diff --git a/nexus3/pkg/task/service.go b/nexus3/pkg/task/service.go new file mode 100644 index 00000000..56f5fa68 --- /dev/null +++ b/nexus3/pkg/task/service.go @@ -0,0 +1,98 @@ +package task + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/datadrivers/go-nexus-client/nexus3/schema" + "net/http" + "net/url" + + "github.com/datadrivers/go-nexus-client/nexus3/pkg/client" + "github.com/datadrivers/go-nexus-client/nexus3/schema/task" +) + +const ( + taskAPIEndpoint = client.BasePath + "v1/tasks" +) + +var ( + ErrTaskNotRunning = errors.New("task is not currently running") +) + +type TaskService client.Service + +func NewTaskService(c *client.Client) *TaskService { + return &TaskService{Client: c} +} + +func (s *TaskService) ListTasks(taskType *string, continuationToken *string) ([]task.Task, *string, error) { + q := url.Values{} + if taskType != nil { + q.Set("type", *taskType) + } + if continuationToken != nil { + q.Set("continuationToken", *continuationToken) + } + + body, resp, err := s.Client.Get(fmt.Sprintf("%s?%s", taskAPIEndpoint, q.Encode()), nil) + if err != nil { + return nil, nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, nil, fmt.Errorf("could not list task: HTTP: %d, %s", resp.StatusCode, string(body)) + } + + var result schema.PaginationResult[task.Task] + if err := json.Unmarshal(body, &result); err != nil { + return nil, nil, fmt.Errorf("could not unmarshal tasks: %v", err) + } + + return result.Items, result.ContinuationToken, nil +} + +func (s *TaskService) GetTask(id string) (*task.Task, error) { + body, resp, err := s.Client.Get(fmt.Sprintf("%s/%s", taskAPIEndpoint, id), nil) + if err != nil { + return nil, err + } + switch resp.StatusCode { + case http.StatusOK: + var t task.Task + if err := json.Unmarshal(body, &t); err != nil { + return nil, fmt.Errorf("could not unmarshal task: %v", err) + } + return &t, nil + case http.StatusNotFound: + return nil, nil + default: + return nil, fmt.Errorf("could not get task '%s': HTTP: %d, %s", id, resp.StatusCode, string(body)) + } +} + +func (s *TaskService) RunTask(id string) error { + body, resp, err := s.Client.Post(fmt.Sprintf("%s/%s/run", taskAPIEndpoint, id), nil) + if err != nil { + return err + } + if resp.StatusCode != http.StatusNoContent { + return fmt.Errorf("could not run task '%s': HTTP: %d, %s", id, resp.StatusCode, string(body)) + } + return nil +} + +func (s *TaskService) StopTask(id string) error { + body, resp, err := s.Client.Post(fmt.Sprintf("%s/%s/stop", taskAPIEndpoint, id), nil) + if err != nil { + return err + } + switch resp.StatusCode { + case http.StatusNoContent: + return nil + case http.StatusConflict: + return ErrTaskNotRunning + default: + return fmt.Errorf("could not stop task '%s': HTTP: %d, %s", id, resp.StatusCode, string(body)) + } +} diff --git a/nexus3/pkg/task/service_test.go b/nexus3/pkg/task/service_test.go new file mode 100644 index 00000000..97c53398 --- /dev/null +++ b/nexus3/pkg/task/service_test.go @@ -0,0 +1,64 @@ +package task + +import ( + "testing" + + "github.com/datadrivers/go-nexus-client/nexus3/pkg/client" + "github.com/datadrivers/go-nexus-client/nexus3/pkg/tools" + "github.com/stretchr/testify/assert" +) + +var ( + testClient *client.Client = nil +) + +func getTestClient() *client.Client { + if testClient != nil { + return testClient + } + return client.NewClient(getDefaultConfig()) +} + +func getTestService() *TaskService { + return NewTaskService(getTestClient()) +} + +func getDefaultConfig() client.Config { + timeout := tools.GetEnv("NEXUS_TIMEOUT", 30).(int) + 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), + Timeout: &timeout, + } +} + +func TestFreezeAndReleaseTaskState(t *testing.T) { + s := getTestService() + + tasks, _, err := s.ListTasks(nil, nil) + if err != nil { + assert.Failf(t, "fail to list task", err.Error()) + return + } + for _, task := range tasks { + assert.NotEmpty(t, task.ID) + assert.NotEmpty(t, task.Name) + assert.NotEmpty(t, task.Type) + assert.NotEmpty(t, task.CurrentState) + } + + // test get task api + if len(tasks) > 0 { + task, err := s.GetTask(tasks[0].ID) + if err != nil { + assert.Failf(t, "fail to run task", err.Error()) + return + } + assert.NotEmpty(t, task.ID) + assert.NotEmpty(t, task.Name) + assert.NotEmpty(t, task.Type) + assert.NotEmpty(t, task.CurrentState) + } +} diff --git a/nexus3/schema/pagination.go b/nexus3/schema/pagination.go new file mode 100644 index 00000000..ed1bdb50 --- /dev/null +++ b/nexus3/schema/pagination.go @@ -0,0 +1,6 @@ +package schema + +type PaginationResult[T any] struct { + Items []T `json:"items"` + ContinuationToken *string `json:"continuationToken"` +} diff --git a/nexus3/schema/task/task.go b/nexus3/schema/task/task.go new file mode 100644 index 00000000..0ae3a9e9 --- /dev/null +++ b/nexus3/schema/task/task.go @@ -0,0 +1,12 @@ +package task + +type Task struct { + ID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Message *string `json:"message"` + CurrentState string `json:"currentState` + LastRunResult *string `json:"lastRunResult` + NextRun *string `json:"nextRun"` + LastRun *string `json:"lastRun"` +}