first with full handle over rpm
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
7948368573
commit
274ea454dd
50 changed files with 4309 additions and 0 deletions
388
client/client.go
Normal file
388
client/client.go
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ErrNotFound = errors.New("repo not found")
|
||||
|
||||
type Client struct {
|
||||
baseURL string
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func New(baseURL string) *Client {
|
||||
return &Client{
|
||||
baseURL: baseURL,
|
||||
httpClient: &http.Client{Timeout: 30 * time.Second},
|
||||
}
|
||||
}
|
||||
|
||||
type CreateRepoInput struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
SourceURL string `json:"source_url"`
|
||||
SyncMode string `json:"sync_mode,omitempty"`
|
||||
}
|
||||
|
||||
type Repo struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
SourceURL string `json:"source_url"`
|
||||
Frozen bool `json:"frozen"`
|
||||
SyncMode string `json:"sync_mode"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type listReposResponse struct {
|
||||
Items []Repo `json:"items"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
func (c *Client) CreateRepo(ctx context.Context, in CreateRepoInput) (*Repo, error) {
|
||||
body, _ := json.Marshal(in)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL+"/api/v1/repos", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
var repo Repo
|
||||
if err := c.do(req, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &repo, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListRepos(ctx context.Context) ([]Repo, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.baseURL+"/api/v1/repos", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp listReposResponse
|
||||
if err := c.do(req, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Items, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetRepo(ctx context.Context, id int64) (*Repo, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/api/v1/repos/%d", c.baseURL, id), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var repo Repo
|
||||
if err := c.do(req, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &repo, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteRepo(ctx context.Context, id int64) error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fmt.Sprintf("%s/api/v1/repos/%d", c.baseURL, id), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.do(req, nil)
|
||||
}
|
||||
|
||||
type StartCloneResponse struct {
|
||||
JobID int64 `json:"job_id"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type CloneStatus struct {
|
||||
JobID int64 `json:"job_id"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
Status string `json:"status"`
|
||||
StartedAt *string `json:"started_at,omitempty"`
|
||||
FinishedAt *string `json:"finished_at,omitempty"`
|
||||
Error *string `json:"error,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
func (c *Client) StartClone(ctx context.Context, repoID int64) (*StartCloneResponse, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/clone", c.baseURL, repoID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp StartCloneResponse
|
||||
if err := c.do(req, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetCloneStatus(ctx context.Context, repoID int64) (*CloneStatus, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/clone/status", c.baseURL, repoID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var status CloneStatus
|
||||
if err := c.do(req, &status); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &status, nil
|
||||
}
|
||||
|
||||
type PendingPackage struct {
|
||||
ID int64 `json:"id"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Arch string `json:"arch"`
|
||||
Location string `json:"location"`
|
||||
Checksum string `json:"checksum"`
|
||||
ChecksumType string `json:"checksum_type"`
|
||||
Size int64 `json:"size"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type listPendingResponse struct {
|
||||
Items []PendingPackage `json:"items"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
type syncSelectionBody struct {
|
||||
IDs []int64 `json:"ids"`
|
||||
}
|
||||
|
||||
func (c *Client) TriggerSync(ctx context.Context, repoID int64) error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/sync/trigger", c.baseURL, repoID), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.do(req, nil)
|
||||
}
|
||||
|
||||
func (c *Client) ListPending(ctx context.Context, repoID int64) ([]PendingPackage, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/sync/pending", c.baseURL, repoID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp listPendingResponse
|
||||
if err := c.do(req, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Items, nil
|
||||
}
|
||||
|
||||
func (c *Client) ApprovePending(ctx context.Context, repoID int64, ids []int64) error {
|
||||
body, _ := json.Marshal(syncSelectionBody{IDs: ids})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/sync/approve", c.baseURL, repoID),
|
||||
bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
return c.do(req, nil)
|
||||
}
|
||||
|
||||
func (c *Client) RejectPending(ctx context.Context, repoID int64, ids []int64) error {
|
||||
body, _ := json.Marshal(syncSelectionBody{IDs: ids})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/sync/reject", c.baseURL, repoID),
|
||||
bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
return c.do(req, nil)
|
||||
}
|
||||
|
||||
type Snapshot struct {
|
||||
ID int64 `json:"id"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
Label string `json:"label"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type SnapshotPackage struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Arch string `json:"arch"`
|
||||
Location string `json:"location"`
|
||||
Checksum string `json:"checksum"`
|
||||
ChecksumType string `json:"checksum_type"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
type SnapshotDetail struct {
|
||||
Snapshot
|
||||
Packages []SnapshotPackage `json:"packages"`
|
||||
}
|
||||
|
||||
type listSnapshotsResponse struct {
|
||||
Items []Snapshot `json:"items"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
type SnapshotDiff struct {
|
||||
From Snapshot `json:"from"`
|
||||
To Snapshot `json:"to"`
|
||||
Added []SnapshotPackage `json:"added"`
|
||||
Removed []SnapshotPackage `json:"removed"`
|
||||
Unchanged int `json:"unchanged"`
|
||||
}
|
||||
|
||||
func (c *Client) CreateSnapshot(ctx context.Context, repoID int64, label string) (*Snapshot, error) {
|
||||
body, _ := json.Marshal(map[string]string{"label": label})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/snapshots", c.baseURL, repoID), bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
var snap Snapshot
|
||||
if err := c.do(req, &snap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &snap, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListSnapshots(ctx context.Context, repoID int64) ([]Snapshot, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/snapshots", c.baseURL, repoID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp listSnapshotsResponse
|
||||
if err := c.do(req, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Items, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetSnapshot(ctx context.Context, repoID, snapID int64) (*SnapshotDetail, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/snapshots/%d", c.baseURL, repoID, snapID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var detail SnapshotDetail
|
||||
if err := c.do(req, &detail); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &detail, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteSnapshot(ctx context.Context, repoID, snapID int64) error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodDelete,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/snapshots/%d", c.baseURL, repoID, snapID), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.do(req, nil)
|
||||
}
|
||||
|
||||
func (c *Client) DiffSnapshots(ctx context.Context, repoID, fromID, toID int64) (*SnapshotDiff, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/snapshots/diff?from=%d&to=%d", c.baseURL, repoID, fromID, toID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var diff SnapshotDiff
|
||||
if err := c.do(req, &diff); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &diff, nil
|
||||
}
|
||||
|
||||
func (c *Client) RollbackSnapshot(ctx context.Context, repoID, snapID int64) error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/snapshots/%d/rollback", c.baseURL, repoID, snapID), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.do(req, nil)
|
||||
}
|
||||
|
||||
type BlockedPackage struct {
|
||||
ID int64 `json:"id"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
Name string `json:"name"`
|
||||
Location string `json:"location"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type listBlockedResponse struct {
|
||||
Items []BlockedPackage `json:"items"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
func (c *Client) BlockPackages(ctx context.Context, repoID int64, pendingIDs []int64) error {
|
||||
body, _ := json.Marshal(syncSelectionBody{IDs: pendingIDs})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/sync/block", c.baseURL, repoID),
|
||||
bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
return c.do(req, nil)
|
||||
}
|
||||
|
||||
func (c *Client) UnblockPackages(ctx context.Context, repoID int64, blockedIDs []int64) error {
|
||||
body, _ := json.Marshal(syncSelectionBody{IDs: blockedIDs})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/sync/unblock", c.baseURL, repoID),
|
||||
bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
return c.do(req, nil)
|
||||
}
|
||||
|
||||
func (c *Client) ListBlocked(ctx context.Context, repoID int64) ([]BlockedPackage, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
|
||||
fmt.Sprintf("%s/api/v1/repos/%d/sync/blocked", c.baseURL, repoID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp listBlockedResponse
|
||||
if err := c.do(req, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Items, nil
|
||||
}
|
||||
|
||||
type errorResponse struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
func (c *Client) do(req *http.Request, out any) error {
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return ErrNotFound
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
var errResp errorResponse
|
||||
json.NewDecoder(resp.Body).Decode(&errResp)
|
||||
if errResp.Error != "" {
|
||||
return fmt.Errorf("%s", errResp.Error)
|
||||
}
|
||||
return fmt.Errorf("unexpected status %d", resp.StatusCode)
|
||||
}
|
||||
if out != nil {
|
||||
return json.NewDecoder(resp.Body).Decode(out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue