187 lines
5.3 KiB
Go
187 lines
5.3 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
type Project struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description,omitempty"`
|
|
Status string `json:"status"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
type ProjectMember struct {
|
|
ProjectID string `json:"project_id"`
|
|
UserID string `json:"user_id"`
|
|
Role string `json:"role"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
type ProjectToken struct {
|
|
ID string `json:"id"`
|
|
ProjectID string `json:"project_id"`
|
|
Name string `json:"name"`
|
|
Prefix string `json:"prefix"`
|
|
Role string `json:"role"`
|
|
CreatedAt string `json:"created_at"`
|
|
ExpiresAt *string `json:"expires_at,omitempty"`
|
|
RevokedAt *string `json:"revoked_at,omitempty"`
|
|
}
|
|
|
|
type CreatedProjectToken struct {
|
|
Token ProjectToken `json:"token"`
|
|
Secret string `json:"secret"`
|
|
}
|
|
|
|
func (c *Client) ListProjects(ctx context.Context) ([]Project, error) {
|
|
var response struct {
|
|
Projects []Project `json:"projects"`
|
|
}
|
|
if err := c.getJSON(ctx, "/api/v1/projects", &response); err != nil {
|
|
return nil, err
|
|
}
|
|
return response.Projects, nil
|
|
}
|
|
|
|
func (c *Client) GetProject(ctx context.Context, project string) (Project, error) {
|
|
project = strings.TrimSpace(project)
|
|
if project == "" {
|
|
return Project{}, errors.New("项目标识不能为空")
|
|
}
|
|
var result Project
|
|
path := "/api/v1/projects/" + url.PathEscape(project)
|
|
if err := c.getJSON(ctx, path, &result); err != nil {
|
|
return Project{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *Client) CreateProject(ctx context.Context, project Project) (Project, error) {
|
|
var result Project
|
|
if err := c.postJSON(ctx, "/api/v1/projects", map[string]string{
|
|
"id": project.ID,
|
|
"name": project.Name,
|
|
"description": project.Description,
|
|
}, &result); err != nil {
|
|
return Project{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *Client) UpdateProject(ctx context.Context, project Project) (Project, error) {
|
|
project.ID = strings.TrimSpace(project.ID)
|
|
if err := validateProjectID(project.ID); err != nil {
|
|
return Project{}, err
|
|
}
|
|
var result Project
|
|
path := "/api/v1/projects/" + url.PathEscape(project.ID)
|
|
if err := c.patchJSON(ctx, path, map[string]string{
|
|
"name": project.Name,
|
|
"description": project.Description,
|
|
"status": project.Status,
|
|
}, &result); err != nil {
|
|
return Project{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *Client) ListProjectMembers(ctx context.Context) ([]ProjectMember, error) {
|
|
var response struct {
|
|
Members []ProjectMember `json:"members"`
|
|
}
|
|
if err := c.getJSON(ctx, c.projectPath("members"), &response); err != nil {
|
|
return nil, err
|
|
}
|
|
return response.Members, nil
|
|
}
|
|
|
|
func (c *Client) AddProjectMember(ctx context.Context, userID, role string) (ProjectMember, error) {
|
|
var result ProjectMember
|
|
if err := c.postJSON(ctx, c.projectPath("members"), map[string]string{"user_id": userID, "role": role}, &result); err != nil {
|
|
return ProjectMember{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *Client) UpdateProjectMember(ctx context.Context, userID, role string) (ProjectMember, error) {
|
|
var result ProjectMember
|
|
path := c.projectPath("members") + "/" + url.PathEscape(strings.TrimSpace(userID))
|
|
if err := c.patchJSON(ctx, path, map[string]string{"role": role}, &result); err != nil {
|
|
return ProjectMember{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *Client) DeleteProjectMember(ctx context.Context, userID string) error {
|
|
path := c.projectPath("members") + "/" + url.PathEscape(strings.TrimSpace(userID))
|
|
request, err := c.newRequest(ctx, http.MethodDelete, path, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
response, err := c.httpClient.Do(request)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer response.Body.Close()
|
|
return checkResponse(response)
|
|
}
|
|
|
|
func (c *Client) ListProjectTokens(ctx context.Context) ([]ProjectToken, error) {
|
|
var response struct {
|
|
Tokens []ProjectToken `json:"tokens"`
|
|
}
|
|
if err := c.getJSON(ctx, c.projectPath("tokens"), &response); err != nil {
|
|
return nil, err
|
|
}
|
|
return response.Tokens, nil
|
|
}
|
|
|
|
func (c *Client) CreateProjectToken(ctx context.Context, name, role string, expiresAt *string) (CreatedProjectToken, error) {
|
|
var result CreatedProjectToken
|
|
input := map[string]string{"name": name, "role": role}
|
|
if expiresAt != nil {
|
|
input["expires_at"] = *expiresAt
|
|
}
|
|
if err := c.postJSON(ctx, c.projectPath("tokens"), input, &result); err != nil {
|
|
return CreatedProjectToken{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *Client) RevokeProjectToken(ctx context.Context, tokenID string) (ProjectToken, error) {
|
|
var result ProjectToken
|
|
path := c.projectPath("tokens") + "/" + url.PathEscape(strings.TrimSpace(tokenID)) + "/revoke"
|
|
if err := c.postJSON(ctx, path, map[string]string{}, &result); err != nil {
|
|
return ProjectToken{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *Client) projectPath(resource string) string {
|
|
if c.project == "" {
|
|
return "/api/v1/projects/" + url.PathEscape(resource)
|
|
}
|
|
return "/api/v1/projects/" + url.PathEscape(c.project) + "/" + url.PathEscape(resource)
|
|
}
|
|
|
|
func (c *Client) ProjectHealth(ctx context.Context) error {
|
|
request, err := c.newRequest(ctx, http.MethodGet, "/healthz", nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
response, err := c.httpClient.Do(request)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer response.Body.Close()
|
|
return checkResponse(response)
|
|
}
|