init
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/iceBear67/simplepages/api"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------- identity
|
||||
|
||||
// WhoAmI describes the credential the client is using.
|
||||
func (c *Client) WhoAmI(ctx context.Context) (api.WhoAmI, error) {
|
||||
var out api.WhoAmI
|
||||
err := c.do(ctx, http.MethodGet, api.PathWhoAmI(), nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// SystemInfo returns server-wide counters. Admin scope only.
|
||||
func (c *Client) SystemInfo(ctx context.Context) (api.SystemInfo, error) {
|
||||
var out api.SystemInfo
|
||||
err := c.do(ctx, http.MethodGet, api.PathSystemInfo(), nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- projects
|
||||
|
||||
// CreateProject creates a project. Admin scope only.
|
||||
func (c *Client) CreateProject(ctx context.Context, req api.CreateProjectRequest) (api.Project, error) {
|
||||
var out api.Project
|
||||
err := c.do(ctx, http.MethodPost, api.PathProjects(), req, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// ListOptions pages a listing endpoint. A zero Limit takes the server default.
|
||||
type ListOptions struct {
|
||||
Limit int
|
||||
Cursor string
|
||||
}
|
||||
|
||||
func (o ListOptions) query() string {
|
||||
q := url.Values{}
|
||||
if o.Limit > 0 {
|
||||
q.Set("limit", strconv.Itoa(o.Limit))
|
||||
}
|
||||
if o.Cursor != "" {
|
||||
q.Set("cursor", o.Cursor)
|
||||
}
|
||||
if len(q) == 0 {
|
||||
return ""
|
||||
}
|
||||
return "?" + q.Encode()
|
||||
}
|
||||
|
||||
// ListProjects returns one page of projects. Admin scope only.
|
||||
func (c *Client) ListProjects(ctx context.Context, opts ListOptions) (api.ProjectList, error) {
|
||||
var out api.ProjectList
|
||||
err := c.do(ctx, http.MethodGet, api.PathProjects()+opts.query(), nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// ListAllProjects follows the cursor to the end.
|
||||
//
|
||||
// The CLI pages on the user's behalf because "pages project list" that silently
|
||||
// showed the first hundred of three hundred projects would be a lie; a caller
|
||||
// that wants one page asks for ListProjects.
|
||||
func (c *Client) ListAllProjects(ctx context.Context) ([]api.Project, error) {
|
||||
var all []api.Project
|
||||
opts := ListOptions{Limit: 500}
|
||||
for {
|
||||
page, err := c.ListProjects(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
all = append(all, page.Projects...)
|
||||
if page.NextCursor == "" || len(page.Projects) == 0 {
|
||||
return all, nil
|
||||
}
|
||||
opts.Cursor = page.NextCursor
|
||||
}
|
||||
}
|
||||
|
||||
// GetProject reads one project. A project-scoped key may read only its own.
|
||||
func (c *Client) GetProject(ctx context.Context, name string) (api.Project, error) {
|
||||
var out api.Project
|
||||
err := c.do(ctx, http.MethodGet, api.PathProject(name), nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// PatchProject applies a partial update. Admin scope only.
|
||||
func (c *Client) PatchProject(ctx context.Context, name string, patch api.ProjectPatch) (api.Project, error) {
|
||||
var out api.Project
|
||||
err := c.do(ctx, http.MethodPatch, api.PathProject(name), patch, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// DeleteProject removes a project and everything under it. Admin scope only.
|
||||
func (c *Client) DeleteProject(ctx context.Context, name string) error {
|
||||
return c.do(ctx, http.MethodDelete, api.PathProject(name), nil, nil)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------- keys
|
||||
|
||||
// CreateAdminKey mints an admin key. Admin scope only.
|
||||
//
|
||||
// The returned token is the only copy that will ever exist; the caller shows it
|
||||
// once and must not log it.
|
||||
func (c *Client) CreateAdminKey(ctx context.Context, req api.CreateKeyRequest) (api.CreateKeyResponse, error) {
|
||||
var out api.CreateKeyResponse
|
||||
err := c.do(ctx, http.MethodPost, api.PathKeys(), req, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// CreateProjectKey mints a key scoped to one project. Admin scope only.
|
||||
func (c *Client) CreateProjectKey(ctx context.Context, project string, req api.CreateKeyRequest) (api.CreateKeyResponse, error) {
|
||||
var out api.CreateKeyResponse
|
||||
err := c.do(ctx, http.MethodPost, api.PathProjectKeys(project), req, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// ListKeys returns every key on the server. Admin scope only.
|
||||
func (c *Client) ListKeys(ctx context.Context) (api.KeyList, error) {
|
||||
var out api.KeyList
|
||||
err := c.do(ctx, http.MethodGet, api.PathKeys(), nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// ListProjectKeys returns the keys of one project.
|
||||
func (c *Client) ListProjectKeys(ctx context.Context, project string) (api.KeyList, error) {
|
||||
var out api.KeyList
|
||||
err := c.do(ctx, http.MethodGet, api.PathProjectKeys(project), nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RevokeKey revokes a key by id. It takes effect immediately, and is
|
||||
// idempotent: revoking an already-revoked key succeeds.
|
||||
func (c *Client) RevokeKey(ctx context.Context, keyID string) error {
|
||||
return c.do(ctx, http.MethodDelete, api.PathKey(keyID), nil, nil)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------- deployments
|
||||
|
||||
// DeploymentListOptions selects and pages a project's deployments. A zero State
|
||||
// lists every state.
|
||||
type DeploymentListOptions struct {
|
||||
ListOptions
|
||||
State string
|
||||
}
|
||||
|
||||
func (o DeploymentListOptions) query() string {
|
||||
q := url.Values{}
|
||||
if o.Limit > 0 {
|
||||
q.Set("limit", strconv.Itoa(o.Limit))
|
||||
}
|
||||
if o.Cursor != "" {
|
||||
q.Set("cursor", o.Cursor)
|
||||
}
|
||||
if o.State != "" {
|
||||
q.Set("state", o.State)
|
||||
}
|
||||
if len(q) == 0 {
|
||||
return ""
|
||||
}
|
||||
return "?" + q.Encode()
|
||||
}
|
||||
|
||||
// ListDeployments returns one page of a project's deployments, newest first.
|
||||
func (c *Client) ListDeployments(ctx context.Context, project string, opts DeploymentListOptions) (api.DeploymentList, error) {
|
||||
var out api.DeploymentList
|
||||
err := c.do(ctx, http.MethodGet, api.PathDeployments(project)+opts.query(), nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// GetDeployment reads one deployment. withFiles asks for its manifest too,
|
||||
// which for a large site is a great deal more response than the rest of it.
|
||||
func (c *Client) GetDeployment(ctx context.Context, project, id string, withFiles bool) (api.Deployment, error) {
|
||||
var out api.Deployment
|
||||
path := api.PathDeployment(project, id)
|
||||
if withFiles {
|
||||
path += "?files=true"
|
||||
}
|
||||
err := c.do(ctx, http.MethodGet, path, nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// DeleteDeployment removes a deployment and its files. The active one cannot be
|
||||
// deleted; the server answers deployment_active until something else is
|
||||
// activated.
|
||||
func (c *Client) DeleteDeployment(ctx context.Context, project, id string) error {
|
||||
return c.do(ctx, http.MethodDelete, api.PathDeployment(project, id), nil, nil)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- upkeep
|
||||
|
||||
// Collect runs a garbage collection pass. Admin scope only.
|
||||
func (c *Client) Collect(ctx context.Context, dryRun bool) (api.GCStats, error) {
|
||||
var out api.GCStats
|
||||
err := c.do(ctx, http.MethodPost, api.PathGC(), api.GCRequest{DryRun: dryRun}, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Fsck checks the blob reference counts against the manifests, optionally
|
||||
// correcting them. Admin scope only.
|
||||
func (c *Client) Fsck(ctx context.Context, repair bool) (api.FsckReport, error) {
|
||||
var out api.FsckReport
|
||||
err := c.do(ctx, http.MethodPost, api.PathFsck(), api.FsckRequest{Repair: repair}, &out)
|
||||
return out, err
|
||||
}
|
||||
Reference in New Issue
Block a user