279 lines
8.4 KiB
Go
279 lines
8.4 KiB
Go
package godo
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
appsBasePath = "/v2/apps"
|
|
)
|
|
|
|
// AppLogType is the type of app logs.
|
|
type AppLogType string
|
|
|
|
const (
|
|
// AppLogTypeBuild represents build logs.
|
|
AppLogTypeBuild AppLogType = "BUILD"
|
|
// AppLogTypeDeploy represents deploy logs.
|
|
AppLogTypeDeploy AppLogType = "DEPLOY"
|
|
// AppLogTypeRun represents run logs.
|
|
AppLogTypeRun AppLogType = "RUN"
|
|
)
|
|
|
|
// AppsService is an interface for interfacing with the App Platform endpoints
|
|
// of the DigitalOcean API.
|
|
type AppsService interface {
|
|
Create(ctx context.Context, create *AppCreateRequest) (*App, *Response, error)
|
|
Get(ctx context.Context, appID string) (*App, *Response, error)
|
|
List(ctx context.Context, opts *ListOptions) ([]*App, *Response, error)
|
|
Update(ctx context.Context, appID string, update *AppUpdateRequest) (*App, *Response, error)
|
|
Delete(ctx context.Context, appID string) (*Response, error)
|
|
|
|
GetDeployment(ctx context.Context, appID, deploymentID string) (*Deployment, *Response, error)
|
|
ListDeployments(ctx context.Context, appID string, opts *ListOptions) ([]*Deployment, *Response, error)
|
|
CreateDeployment(ctx context.Context, appID string) (*Deployment, *Response, error)
|
|
|
|
GetLogs(ctx context.Context, appID, deploymentID, component string, logType AppLogType, follow bool) (*AppLogs, *Response, error)
|
|
}
|
|
|
|
// App represents an app.
|
|
type App struct {
|
|
ID string `json:"id"`
|
|
Spec *AppSpec `json:"spec"`
|
|
DefaultIngress string `json:"default_ingress"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
|
ActiveDeployment *Deployment `json:"active_deployment,omitempty"`
|
|
InProgressDeployment *Deployment `json:"in_progress_deployment,omitempty"`
|
|
}
|
|
|
|
// Deployment represents a deployment for an app.
|
|
type Deployment struct {
|
|
ID string `json:"id"`
|
|
Spec *AppSpec `json:"spec"`
|
|
Services []*DeploymentService `json:"services,omitempty"`
|
|
Workers []*DeploymentWorker `json:"workers,omitempty"`
|
|
StaticSites []*DeploymentStaticSite `json:"static_sites,omitempty"`
|
|
|
|
Cause string `json:"cause"`
|
|
Progress *DeploymentProgress `json:"progress"`
|
|
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
|
}
|
|
|
|
// DeploymentService represents a service component in a deployment.
|
|
type DeploymentService struct {
|
|
Name string `json:"name,omitempty"`
|
|
SourceCommitHash string `json:"source_commit_hash"`
|
|
}
|
|
|
|
// DeploymentWorker represents a worker component in a deployment.
|
|
type DeploymentWorker struct {
|
|
Name string `json:"name,omitempty"`
|
|
SourceCommitHash string `json:"source_commit_hash"`
|
|
}
|
|
|
|
// DeploymentStaticSite represents a static site component in a deployment.
|
|
type DeploymentStaticSite struct {
|
|
Name string `json:"name,omitempty"`
|
|
SourceCommitHash string `json:"source_commit_hash"`
|
|
}
|
|
|
|
// DeploymentProgress represents the total progress of a deployment.
|
|
type DeploymentProgress struct {
|
|
PendingSteps int `json:"pending_steps"`
|
|
RunningSteps int `json:"running_steps"`
|
|
SuccessSteps int `json:"success_steps"`
|
|
ErrorSteps int `json:"error_steps"`
|
|
TotalSteps int `json:"total_steps"`
|
|
|
|
Steps []*DeploymentProgressStep `json:"steps"`
|
|
}
|
|
|
|
// DeploymentProgressStep represents the progress of a deployment step.
|
|
type DeploymentProgressStep struct {
|
|
Name string `json:"name"`
|
|
Status string `json:"status"`
|
|
Steps []*DeploymentProgressStep `json:"steps,omitempty"`
|
|
Attempts uint32 `json:"attempts"`
|
|
StartedAt time.Time `json:"started_at,omitempty"`
|
|
EndedAt time.Time `json:"ended_at,omitempty"`
|
|
}
|
|
|
|
// AppLogs represent app logs.
|
|
type AppLogs struct {
|
|
LiveURL string `json:"live_url"`
|
|
HistoricURLs []string `json:"historic_urls"`
|
|
}
|
|
|
|
// AppCreateRequest represents a request to create an app.
|
|
type AppCreateRequest struct {
|
|
Spec *AppSpec `json:"spec"`
|
|
}
|
|
|
|
// AppUpdateRequest represents a request to update an app.
|
|
type AppUpdateRequest struct {
|
|
Spec *AppSpec `json:"spec"`
|
|
}
|
|
|
|
type appRoot struct {
|
|
App *App `json:"app"`
|
|
}
|
|
|
|
type appsRoot struct {
|
|
Apps []*App `json:"apps"`
|
|
}
|
|
|
|
type deploymentRoot struct {
|
|
Deployment *Deployment `json:"deployment"`
|
|
}
|
|
|
|
type deploymentsRoot struct {
|
|
Deployments []*Deployment `json:"deployments"`
|
|
}
|
|
|
|
// AppsServiceOp handles communication with Apps methods of the DigitalOcean API.
|
|
type AppsServiceOp struct {
|
|
client *Client
|
|
}
|
|
|
|
// Creates an app.
|
|
func (s *AppsServiceOp) Create(ctx context.Context, create *AppCreateRequest) (*App, *Response, error) {
|
|
path := appsBasePath
|
|
req, err := s.client.NewRequest(ctx, http.MethodPost, path, create)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
root := new(appRoot)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return root.App, resp, nil
|
|
}
|
|
|
|
// Get an app.
|
|
func (s *AppsServiceOp) Get(ctx context.Context, appID string) (*App, *Response, error) {
|
|
path := fmt.Sprintf("%s/%s", appsBasePath, appID)
|
|
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
root := new(appRoot)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return root.App, resp, nil
|
|
}
|
|
|
|
// List apps.
|
|
func (s *AppsServiceOp) List(ctx context.Context, opts *ListOptions) ([]*App, *Response, error) {
|
|
path := appsBasePath
|
|
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
root := new(appsRoot)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return root.Apps, resp, nil
|
|
}
|
|
|
|
// Update an app.
|
|
func (s *AppsServiceOp) Update(ctx context.Context, appID string, update *AppUpdateRequest) (*App, *Response, error) {
|
|
path := fmt.Sprintf("%s/%s", appsBasePath, appID)
|
|
req, err := s.client.NewRequest(ctx, http.MethodPut, path, update)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
root := new(appRoot)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return root.App, resp, nil
|
|
}
|
|
|
|
// Delete an app.
|
|
func (s *AppsServiceOp) Delete(ctx context.Context, appID string) (*Response, error) {
|
|
path := fmt.Sprintf("%s/%s", appsBasePath, appID)
|
|
req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp, err := s.client.Do(ctx, req, nil)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
// GetDeployment gets an app deployment.
|
|
func (s *AppsServiceOp) GetDeployment(ctx context.Context, appID, deploymentID string) (*Deployment, *Response, error) {
|
|
path := fmt.Sprintf("%s/%s/deployments/%s", appsBasePath, appID, deploymentID)
|
|
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
root := new(deploymentRoot)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return root.Deployment, resp, nil
|
|
}
|
|
|
|
// ListDeployments lists an app deployments.
|
|
func (s *AppsServiceOp) ListDeployments(ctx context.Context, appID string, opts *ListOptions) ([]*Deployment, *Response, error) {
|
|
path := fmt.Sprintf("%s/%s/deployments", appsBasePath, appID)
|
|
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
root := new(deploymentsRoot)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return root.Deployments, resp, nil
|
|
}
|
|
|
|
// CreateDeployment creates an app deployment.
|
|
func (s *AppsServiceOp) CreateDeployment(ctx context.Context, appID string) (*Deployment, *Response, error) {
|
|
path := fmt.Sprintf("%s/%s/deployments", appsBasePath, appID)
|
|
req, err := s.client.NewRequest(ctx, http.MethodPost, path, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
root := new(deploymentRoot)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return root.Deployment, resp, nil
|
|
}
|
|
|
|
// GetLogs retrieves app logs.
|
|
func (s *AppsServiceOp) GetLogs(ctx context.Context, appID, deploymentID, component string, logType AppLogType, follow bool) (*AppLogs, *Response, error) {
|
|
url := fmt.Sprintf("%s/%s/deployments/%s/components/%s/logs?type=%s&follow=%t", appsBasePath, appID, deploymentID, component, logType, follow)
|
|
req, err := s.client.NewRequest(ctx, http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
logs := new(AppLogs)
|
|
resp, err := s.client.Do(ctx, req, logs)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return logs, resp, nil
|
|
}
|