diff --git a/api/apiv1/design/api.go b/api/apiv1/design/api.go index bf432507..d2266373 100644 --- a/api/apiv1/design/api.go +++ b/api/apiv1/design/api.go @@ -526,6 +526,156 @@ var _ = g.Service("control-plane", func() { g.Meta("openapi:tag:Database") }) }) + g.Method("list-host-tasks", func() { + g.Description("Lists all tasks for a host.") + g.Meta("openapi:summary", "List host tasks") + g.Payload(func() { + g.Attribute("host_id", Identifier, func() { + g.Description("ID of the host to list tasks for.") + g.Example("host-1") + }) + g.Attribute("after_task_id", g.String, func() { + g.Description("ID of the task to start from.") + g.Format(g.FormatUUID) + g.Example("3c875a27-f6a6-4c1c-ba5f-6972fb1fc348") + }) + g.Attribute("limit", g.Int, func() { + g.Description("Maximum number of tasks to return.") + g.Example(100) + }) + g.Attribute("sort_order", g.String, func() { + g.Enum("asc", "ascend", "ascending", "desc", "descend", "descending") + g.Description("Sort order for the tasks.") + g.Example("ascend") + }) + + g.Required("host_id") + }) + g.Result(ListHostTasksResponse) + g.Error("cluster_not_initialized") + g.Error("invalid_input") + g.Error("not_found") + + g.HTTP(func() { + g.GET("/v1/hosts/{host_id}/tasks") + g.Param("after_task_id") + g.Param("limit") + g.Param("sort_order") + + g.Meta("openapi:tag:Host") + }) + }) + + g.Method("get-host-task", func() { + g.Description("Returns information about a particular task for a host.") + g.Meta("openapi:summary", "Get host task") + g.Payload(func() { + g.Attribute("host_id", Identifier, func() { + g.Description("ID of the host the task belongs to.") + g.Example("host-1") + }) + g.Attribute("task_id", g.String, func() { + g.Description("ID of the task to get.") + g.Format(g.FormatUUID) + g.Example("3c875a27-f6a6-4c1c-ba5f-6972fb1fc348") + }) + + g.Required("host_id", "task_id") + }) + g.Result(Task) + g.Error("cluster_not_initialized") + g.Error("invalid_input") + g.Error("not_found") + + g.HTTP(func() { + g.GET("/v1/hosts/{host_id}/tasks/{task_id}") + + g.Meta("openapi:tag:Host") + }) + }) + + g.Method("get-host-task-log", func() { + g.Description("Returns the log of a particular task for a host.") + g.Meta("openapi:summary", "Get host task logs") + g.Payload(func() { + g.Attribute("host_id", Identifier, func() { + g.Description("ID of the host to get the task logs for.") + g.Example("host-1") + }) + g.Attribute("task_id", g.String, func() { + g.Description("ID of the task to get the logs for.") + g.Format(g.FormatUUID) + g.Example("3c875a27-f6a6-4c1c-ba5f-6972fb1fc348") + }) + g.Attribute("after_entry_id", g.String, func() { + g.Description("ID of the entry to start from.") + g.Format(g.FormatUUID) + g.Example("3c875a27-f6a6-4c1c-ba5f-6972fb1fc348") + }) + g.Attribute("limit", g.Int, func() { + g.Description("Maximum number of entries to return.") + g.Example(100) + }) + + g.Required("host_id", "task_id") + }) + g.Result(TaskLog) + g.Error("cluster_not_initialized") + g.Error("invalid_input") + g.Error("not_found") + + g.HTTP(func() { + g.GET("/v1/hosts/{host_id}/tasks/{task_id}/logs") + g.Param("after_entry_id") + g.Param("limit") + + g.Meta("openapi:tag:Host") + }) + }) + + g.Method("list-tasks", func() { + g.Description("Lists tasks across all scopes with optional filtering by scope and entity ID.") + g.Meta("openapi:summary", "List tasks") + g.Payload(func() { + g.Attribute("scope", g.String, func() { + g.Enum("database", "host") + g.Description("Optional scope to filter tasks (database or host).") + g.Example("database") + }) + g.Attribute("entity_id", Identifier, func() { + g.Description("Optional entity ID to filter tasks. Requires scope to be set.") + g.Example("my-app") + }) + g.Attribute("after_task_id", g.String, func() { + g.Description("ID of the task to start from.") + g.Format(g.FormatUUID) + g.Example("3c875a27-f6a6-4c1c-ba5f-6972fb1fc348") + }) + g.Attribute("limit", g.Int, func() { + g.Description("Maximum number of tasks to return.") + g.Example(100) + }) + g.Attribute("sort_order", g.String, func() { + g.Enum("asc", "ascend", "ascending", "desc", "descend", "descending") + g.Description("Sort order for the tasks.") + g.Example("ascend") + }) + }) + g.Result(ListTasksResponse) + g.Error("cluster_not_initialized") + g.Error("invalid_input") + + g.HTTP(func() { + g.GET("/v1/tasks") + g.Param("scope") + g.Param("entity_id") + g.Param("after_task_id") + g.Param("limit") + g.Param("sort_order") + + g.Meta("openapi:tag:System") + }) + }) g.Method("restore-database", func() { g.Description("Perform an in-place restore of one or more nodes using the given restore configuration.") diff --git a/api/apiv1/design/task.go b/api/apiv1/design/task.go index 5dc0bcc8..dc61bb08 100644 --- a/api/apiv1/design/task.go +++ b/api/apiv1/design/task.go @@ -310,3 +310,52 @@ var ListDatabaseTasksResponse = g.Type("ListDatabaseTasksResponse", func() { }, }) }) + +var ListHostTasksResponse = g.Type("ListHostTasksResponse", func() { + g.Attribute("tasks", g.ArrayOf(Task)) + + g.Example(map[string]any{ + "tasks": []map[string]any{ + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "scope": "host", + "entity_id": "host-1", + "host_id": "host-1", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "remove_host", + }, + }, + }) +}) + +var ListTasksResponse = g.Type("ListTasksResponse", func() { + g.Attribute("tasks", g.ArrayOf(Task)) + + g.Example(map[string]any{ + "tasks": []map[string]any{ + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "scope": "database", + "entity_id": "storefront", + "database_id": "storefront", + "instance_id": "storefront-n1-689qacsi", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "node_backup", + }, + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "scope": "host", + "entity_id": "host-1", + "host_id": "host-1", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "remove_host", + }, + }, + }) +}) diff --git a/api/apiv1/gen/control_plane/client.go b/api/apiv1/gen/control_plane/client.go index 67d001c8..9ee0c69c 100644 --- a/api/apiv1/gen/control_plane/client.go +++ b/api/apiv1/gen/control_plane/client.go @@ -34,6 +34,10 @@ type Client struct { ListDatabaseTasksEndpoint goa.Endpoint GetDatabaseTaskEndpoint goa.Endpoint GetDatabaseTaskLogEndpoint goa.Endpoint + ListHostTasksEndpoint goa.Endpoint + GetHostTaskEndpoint goa.Endpoint + GetHostTaskLogEndpoint goa.Endpoint + ListTasksEndpoint goa.Endpoint RestoreDatabaseEndpoint goa.Endpoint GetVersionEndpoint goa.Endpoint RestartInstanceEndpoint goa.Endpoint @@ -43,7 +47,7 @@ type Client struct { } // NewClient initializes a "control-plane" service client given the endpoints. -func NewClient(initCluster, joinCluster, getJoinToken, getJoinOptions, getCluster, listHosts, getHost, removeHost, listDatabases, createDatabase, getDatabase, updateDatabase, deleteDatabase, backupDatabaseNode, switchoverDatabaseNode, failoverDatabaseNode, listDatabaseTasks, getDatabaseTask, getDatabaseTaskLog, restoreDatabase, getVersion, restartInstance, stopInstance, startInstance, cancelDatabaseTask goa.Endpoint) *Client { +func NewClient(initCluster, joinCluster, getJoinToken, getJoinOptions, getCluster, listHosts, getHost, removeHost, listDatabases, createDatabase, getDatabase, updateDatabase, deleteDatabase, backupDatabaseNode, switchoverDatabaseNode, failoverDatabaseNode, listDatabaseTasks, getDatabaseTask, getDatabaseTaskLog, listHostTasks, getHostTask, getHostTaskLog, listTasks, restoreDatabase, getVersion, restartInstance, stopInstance, startInstance, cancelDatabaseTask goa.Endpoint) *Client { return &Client{ InitClusterEndpoint: initCluster, JoinClusterEndpoint: joinCluster, @@ -64,6 +68,10 @@ func NewClient(initCluster, joinCluster, getJoinToken, getJoinOptions, getCluste ListDatabaseTasksEndpoint: listDatabaseTasks, GetDatabaseTaskEndpoint: getDatabaseTask, GetDatabaseTaskLogEndpoint: getDatabaseTaskLog, + ListHostTasksEndpoint: listHostTasks, + GetHostTaskEndpoint: getHostTask, + GetHostTaskLogEndpoint: getHostTaskLog, + ListTasksEndpoint: listTasks, RestoreDatabaseEndpoint: restoreDatabase, GetVersionEndpoint: getVersion, RestartInstanceEndpoint: restartInstance, @@ -387,6 +395,72 @@ func (c *Client) GetDatabaseTaskLog(ctx context.Context, p *GetDatabaseTaskLogPa return ires.(*TaskLog), nil } +// ListHostTasks calls the "list-host-tasks" endpoint of the "control-plane" +// service. +// ListHostTasks may return the following errors: +// - "cluster_not_initialized" (type *goa.ServiceError) +// - "invalid_input" (type *goa.ServiceError) +// - "not_found" (type *goa.ServiceError) +// - "server_error" (type *goa.ServiceError) +// - error: internal error +func (c *Client) ListHostTasks(ctx context.Context, p *ListHostTasksPayload) (res *ListHostTasksResponse, err error) { + var ires any + ires, err = c.ListHostTasksEndpoint(ctx, p) + if err != nil { + return + } + return ires.(*ListHostTasksResponse), nil +} + +// GetHostTask calls the "get-host-task" endpoint of the "control-plane" +// service. +// GetHostTask may return the following errors: +// - "cluster_not_initialized" (type *goa.ServiceError) +// - "invalid_input" (type *goa.ServiceError) +// - "not_found" (type *goa.ServiceError) +// - "server_error" (type *goa.ServiceError) +// - error: internal error +func (c *Client) GetHostTask(ctx context.Context, p *GetHostTaskPayload) (res *Task, err error) { + var ires any + ires, err = c.GetHostTaskEndpoint(ctx, p) + if err != nil { + return + } + return ires.(*Task), nil +} + +// GetHostTaskLog calls the "get-host-task-log" endpoint of the "control-plane" +// service. +// GetHostTaskLog may return the following errors: +// - "cluster_not_initialized" (type *goa.ServiceError) +// - "invalid_input" (type *goa.ServiceError) +// - "not_found" (type *goa.ServiceError) +// - "server_error" (type *goa.ServiceError) +// - error: internal error +func (c *Client) GetHostTaskLog(ctx context.Context, p *GetHostTaskLogPayload) (res *TaskLog, err error) { + var ires any + ires, err = c.GetHostTaskLogEndpoint(ctx, p) + if err != nil { + return + } + return ires.(*TaskLog), nil +} + +// ListTasks calls the "list-tasks" endpoint of the "control-plane" service. +// ListTasks may return the following errors: +// - "cluster_not_initialized" (type *goa.ServiceError) +// - "invalid_input" (type *goa.ServiceError) +// - "server_error" (type *goa.ServiceError) +// - error: internal error +func (c *Client) ListTasks(ctx context.Context, p *ListTasksPayload) (res *ListTasksResponse, err error) { + var ires any + ires, err = c.ListTasksEndpoint(ctx, p) + if err != nil { + return + } + return ires.(*ListTasksResponse), nil +} + // RestoreDatabase calls the "restore-database" endpoint of the "control-plane" // service. // RestoreDatabase may return the following errors: diff --git a/api/apiv1/gen/control_plane/endpoints.go b/api/apiv1/gen/control_plane/endpoints.go index cd39e1ea..db650d1a 100644 --- a/api/apiv1/gen/control_plane/endpoints.go +++ b/api/apiv1/gen/control_plane/endpoints.go @@ -34,6 +34,10 @@ type Endpoints struct { ListDatabaseTasks goa.Endpoint GetDatabaseTask goa.Endpoint GetDatabaseTaskLog goa.Endpoint + ListHostTasks goa.Endpoint + GetHostTask goa.Endpoint + GetHostTaskLog goa.Endpoint + ListTasks goa.Endpoint RestoreDatabase goa.Endpoint GetVersion goa.Endpoint RestartInstance goa.Endpoint @@ -64,6 +68,10 @@ func NewEndpoints(s Service) *Endpoints { ListDatabaseTasks: NewListDatabaseTasksEndpoint(s), GetDatabaseTask: NewGetDatabaseTaskEndpoint(s), GetDatabaseTaskLog: NewGetDatabaseTaskLogEndpoint(s), + ListHostTasks: NewListHostTasksEndpoint(s), + GetHostTask: NewGetHostTaskEndpoint(s), + GetHostTaskLog: NewGetHostTaskLogEndpoint(s), + ListTasks: NewListTasksEndpoint(s), RestoreDatabase: NewRestoreDatabaseEndpoint(s), GetVersion: NewGetVersionEndpoint(s), RestartInstance: NewRestartInstanceEndpoint(s), @@ -95,6 +103,10 @@ func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) { e.ListDatabaseTasks = m(e.ListDatabaseTasks) e.GetDatabaseTask = m(e.GetDatabaseTask) e.GetDatabaseTaskLog = m(e.GetDatabaseTaskLog) + e.ListHostTasks = m(e.ListHostTasks) + e.GetHostTask = m(e.GetHostTask) + e.GetHostTaskLog = m(e.GetHostTaskLog) + e.ListTasks = m(e.ListTasks) e.RestoreDatabase = m(e.RestoreDatabase) e.GetVersion = m(e.GetVersion) e.RestartInstance = m(e.RestartInstance) @@ -280,6 +292,42 @@ func NewGetDatabaseTaskLogEndpoint(s Service) goa.Endpoint { } } +// NewListHostTasksEndpoint returns an endpoint function that calls the method +// "list-host-tasks" of service "control-plane". +func NewListHostTasksEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + p := req.(*ListHostTasksPayload) + return s.ListHostTasks(ctx, p) + } +} + +// NewGetHostTaskEndpoint returns an endpoint function that calls the method +// "get-host-task" of service "control-plane". +func NewGetHostTaskEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + p := req.(*GetHostTaskPayload) + return s.GetHostTask(ctx, p) + } +} + +// NewGetHostTaskLogEndpoint returns an endpoint function that calls the method +// "get-host-task-log" of service "control-plane". +func NewGetHostTaskLogEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + p := req.(*GetHostTaskLogPayload) + return s.GetHostTaskLog(ctx, p) + } +} + +// NewListTasksEndpoint returns an endpoint function that calls the method +// "list-tasks" of service "control-plane". +func NewListTasksEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + p := req.(*ListTasksPayload) + return s.ListTasks(ctx, p) + } +} + // NewRestoreDatabaseEndpoint returns an endpoint function that calls the // method "restore-database" of service "control-plane". func NewRestoreDatabaseEndpoint(s Service) goa.Endpoint { diff --git a/api/apiv1/gen/control_plane/service.go b/api/apiv1/gen/control_plane/service.go index 1cd20270..e231c6ee 100644 --- a/api/apiv1/gen/control_plane/service.go +++ b/api/apiv1/gen/control_plane/service.go @@ -54,6 +54,14 @@ type Service interface { GetDatabaseTask(context.Context, *GetDatabaseTaskPayload) (res *Task, err error) // Returns the log of a particular task for a database. GetDatabaseTaskLog(context.Context, *GetDatabaseTaskLogPayload) (res *TaskLog, err error) + // Lists all tasks for a host. + ListHostTasks(context.Context, *ListHostTasksPayload) (res *ListHostTasksResponse, err error) + // Returns information about a particular task for a host. + GetHostTask(context.Context, *GetHostTaskPayload) (res *Task, err error) + // Returns the log of a particular task for a host. + GetHostTaskLog(context.Context, *GetHostTaskLogPayload) (res *TaskLog, err error) + // Lists tasks across all scopes with optional filtering by scope and entity ID. + ListTasks(context.Context, *ListTasksPayload) (res *ListTasksResponse, err error) // Perform an in-place restore of one or more nodes using the given restore // configuration. RestoreDatabase(context.Context, *RestoreDatabasePayload) (res *RestoreDatabaseResponse, err error) @@ -84,7 +92,7 @@ const ServiceName = "control-plane" // MethodNames lists the service method names as defined in the design. These // are the same values that are set in the endpoint request contexts under the // MethodKey key. -var MethodNames = [25]string{"init-cluster", "join-cluster", "get-join-token", "get-join-options", "get-cluster", "list-hosts", "get-host", "remove-host", "list-databases", "create-database", "get-database", "update-database", "delete-database", "backup-database-node", "switchover-database-node", "failover-database-node", "list-database-tasks", "get-database-task", "get-database-task-log", "restore-database", "get-version", "restart-instance", "stop-instance", "start-instance", "cancel-database-task"} +var MethodNames = [29]string{"init-cluster", "join-cluster", "get-join-token", "get-join-options", "get-cluster", "list-hosts", "get-host", "remove-host", "list-databases", "create-database", "get-database", "update-database", "delete-database", "backup-database-node", "switchover-database-node", "failover-database-node", "list-database-tasks", "get-database-task", "get-database-task-log", "list-host-tasks", "get-host-task", "get-host-task-log", "list-tasks", "restore-database", "get-version", "restart-instance", "stop-instance", "start-instance", "cancel-database-task"} // A Control Plane API error. type APIError struct { @@ -507,6 +515,28 @@ type GetHostPayload struct { HostID Identifier } +// GetHostTaskLogPayload is the payload type of the control-plane service +// get-host-task-log method. +type GetHostTaskLogPayload struct { + // ID of the host to get the task logs for. + HostID Identifier + // ID of the task to get the logs for. + TaskID string + // ID of the entry to start from. + AfterEntryID *string + // Maximum number of entries to return. + Limit *int +} + +// GetHostTaskPayload is the payload type of the control-plane service +// get-host-task method. +type GetHostTaskPayload struct { + // ID of the host the task belongs to. + HostID Identifier + // ID of the task to get. + TaskID string +} + // Host is the result type of the control-plane service get-host method. type Host struct { // Unique identifier for the host. @@ -656,6 +686,25 @@ type ListDatabasesResponse struct { Databases DatabaseCollection } +// ListHostTasksPayload is the payload type of the control-plane service +// list-host-tasks method. +type ListHostTasksPayload struct { + // ID of the host to list tasks for. + HostID Identifier + // ID of the task to start from. + AfterTaskID *string + // Maximum number of tasks to return. + Limit *int + // Sort order for the tasks. + SortOrder *string +} + +// ListHostTasksResponse is the result type of the control-plane service +// list-host-tasks method. +type ListHostTasksResponse struct { + Tasks []*Task +} + // ListHostsResponse is the result type of the control-plane service list-hosts // method. type ListHostsResponse struct { @@ -663,6 +712,27 @@ type ListHostsResponse struct { Hosts []*Host } +// ListTasksPayload is the payload type of the control-plane service list-tasks +// method. +type ListTasksPayload struct { + // Optional scope to filter tasks (database or host). + Scope *string + // Optional entity ID to filter tasks. Requires scope to be set. + EntityID *Identifier + // ID of the task to start from. + AfterTaskID *string + // Maximum number of tasks to return. + Limit *int + // Sort order for the tasks. + SortOrder *string +} + +// ListTasksResponse is the result type of the control-plane service list-tasks +// method. +type ListTasksResponse struct { + Tasks []*Task +} + // Options specific to the selected orchestrator. type OrchestratorOpts struct { // Swarm-specific configuration. diff --git a/api/apiv1/gen/http/cli/control_plane/cli.go b/api/apiv1/gen/http/cli/control_plane/cli.go index 40c64cc2..80cbc3b0 100644 --- a/api/apiv1/gen/http/cli/control_plane/cli.go +++ b/api/apiv1/gen/http/cli/control_plane/cli.go @@ -23,7 +23,7 @@ import ( // command (subcommand1|subcommand2|...) func UsageCommands() []string { return []string{ - "control-plane (init-cluster|join-cluster|get-join-token|get-join-options|get-cluster|list-hosts|get-host|remove-host|list-databases|create-database|get-database|update-database|delete-database|backup-database-node|switchover-database-node|failover-database-node|list-database-tasks|get-database-task|get-database-task-log|restore-database|get-version|restart-instance|stop-instance|start-instance|cancel-database-task)", + "control-plane (init-cluster|join-cluster|get-join-token|get-join-options|get-cluster|list-hosts|get-host|remove-host|list-databases|create-database|get-database|update-database|delete-database|backup-database-node|switchover-database-node|failover-database-node|list-database-tasks|get-database-task|get-database-task-log|list-host-tasks|get-host-task|get-host-task-log|list-tasks|restore-database|get-version|restart-instance|stop-instance|start-instance|cancel-database-task)", } } @@ -116,6 +116,29 @@ func ParseEndpoint( controlPlaneGetDatabaseTaskLogAfterEntryIDFlag = controlPlaneGetDatabaseTaskLogFlags.String("after-entry-id", "", "") controlPlaneGetDatabaseTaskLogLimitFlag = controlPlaneGetDatabaseTaskLogFlags.String("limit", "", "") + controlPlaneListHostTasksFlags = flag.NewFlagSet("list-host-tasks", flag.ExitOnError) + controlPlaneListHostTasksHostIDFlag = controlPlaneListHostTasksFlags.String("host-id", "REQUIRED", "ID of the host to list tasks for.") + controlPlaneListHostTasksAfterTaskIDFlag = controlPlaneListHostTasksFlags.String("after-task-id", "", "") + controlPlaneListHostTasksLimitFlag = controlPlaneListHostTasksFlags.String("limit", "", "") + controlPlaneListHostTasksSortOrderFlag = controlPlaneListHostTasksFlags.String("sort-order", "", "") + + controlPlaneGetHostTaskFlags = flag.NewFlagSet("get-host-task", flag.ExitOnError) + controlPlaneGetHostTaskHostIDFlag = controlPlaneGetHostTaskFlags.String("host-id", "REQUIRED", "ID of the host the task belongs to.") + controlPlaneGetHostTaskTaskIDFlag = controlPlaneGetHostTaskFlags.String("task-id", "REQUIRED", "ID of the task to get.") + + controlPlaneGetHostTaskLogFlags = flag.NewFlagSet("get-host-task-log", flag.ExitOnError) + controlPlaneGetHostTaskLogHostIDFlag = controlPlaneGetHostTaskLogFlags.String("host-id", "REQUIRED", "ID of the host to get the task logs for.") + controlPlaneGetHostTaskLogTaskIDFlag = controlPlaneGetHostTaskLogFlags.String("task-id", "REQUIRED", "ID of the task to get the logs for.") + controlPlaneGetHostTaskLogAfterEntryIDFlag = controlPlaneGetHostTaskLogFlags.String("after-entry-id", "", "") + controlPlaneGetHostTaskLogLimitFlag = controlPlaneGetHostTaskLogFlags.String("limit", "", "") + + controlPlaneListTasksFlags = flag.NewFlagSet("list-tasks", flag.ExitOnError) + controlPlaneListTasksScopeFlag = controlPlaneListTasksFlags.String("scope", "", "") + controlPlaneListTasksEntityIDFlag = controlPlaneListTasksFlags.String("entity-id", "", "") + controlPlaneListTasksAfterTaskIDFlag = controlPlaneListTasksFlags.String("after-task-id", "", "") + controlPlaneListTasksLimitFlag = controlPlaneListTasksFlags.String("limit", "", "") + controlPlaneListTasksSortOrderFlag = controlPlaneListTasksFlags.String("sort-order", "", "") + controlPlaneRestoreDatabaseFlags = flag.NewFlagSet("restore-database", flag.ExitOnError) controlPlaneRestoreDatabaseBodyFlag = controlPlaneRestoreDatabaseFlags.String("body", "REQUIRED", "") controlPlaneRestoreDatabaseDatabaseIDFlag = controlPlaneRestoreDatabaseFlags.String("database-id", "REQUIRED", "ID of the database to restore.") @@ -162,6 +185,10 @@ func ParseEndpoint( controlPlaneListDatabaseTasksFlags.Usage = controlPlaneListDatabaseTasksUsage controlPlaneGetDatabaseTaskFlags.Usage = controlPlaneGetDatabaseTaskUsage controlPlaneGetDatabaseTaskLogFlags.Usage = controlPlaneGetDatabaseTaskLogUsage + controlPlaneListHostTasksFlags.Usage = controlPlaneListHostTasksUsage + controlPlaneGetHostTaskFlags.Usage = controlPlaneGetHostTaskUsage + controlPlaneGetHostTaskLogFlags.Usage = controlPlaneGetHostTaskLogUsage + controlPlaneListTasksFlags.Usage = controlPlaneListTasksUsage controlPlaneRestoreDatabaseFlags.Usage = controlPlaneRestoreDatabaseUsage controlPlaneGetVersionFlags.Usage = controlPlaneGetVersionUsage controlPlaneRestartInstanceFlags.Usage = controlPlaneRestartInstanceUsage @@ -260,6 +287,18 @@ func ParseEndpoint( case "get-database-task-log": epf = controlPlaneGetDatabaseTaskLogFlags + case "list-host-tasks": + epf = controlPlaneListHostTasksFlags + + case "get-host-task": + epf = controlPlaneGetHostTaskFlags + + case "get-host-task-log": + epf = controlPlaneGetHostTaskLogFlags + + case "list-tasks": + epf = controlPlaneListTasksFlags + case "restore-database": epf = controlPlaneRestoreDatabaseFlags @@ -356,6 +395,18 @@ func ParseEndpoint( case "get-database-task-log": endpoint = c.GetDatabaseTaskLog() data, err = controlplanec.BuildGetDatabaseTaskLogPayload(*controlPlaneGetDatabaseTaskLogDatabaseIDFlag, *controlPlaneGetDatabaseTaskLogTaskIDFlag, *controlPlaneGetDatabaseTaskLogAfterEntryIDFlag, *controlPlaneGetDatabaseTaskLogLimitFlag) + case "list-host-tasks": + endpoint = c.ListHostTasks() + data, err = controlplanec.BuildListHostTasksPayload(*controlPlaneListHostTasksHostIDFlag, *controlPlaneListHostTasksAfterTaskIDFlag, *controlPlaneListHostTasksLimitFlag, *controlPlaneListHostTasksSortOrderFlag) + case "get-host-task": + endpoint = c.GetHostTask() + data, err = controlplanec.BuildGetHostTaskPayload(*controlPlaneGetHostTaskHostIDFlag, *controlPlaneGetHostTaskTaskIDFlag) + case "get-host-task-log": + endpoint = c.GetHostTaskLog() + data, err = controlplanec.BuildGetHostTaskLogPayload(*controlPlaneGetHostTaskLogHostIDFlag, *controlPlaneGetHostTaskLogTaskIDFlag, *controlPlaneGetHostTaskLogAfterEntryIDFlag, *controlPlaneGetHostTaskLogLimitFlag) + case "list-tasks": + endpoint = c.ListTasks() + data, err = controlplanec.BuildListTasksPayload(*controlPlaneListTasksScopeFlag, *controlPlaneListTasksEntityIDFlag, *controlPlaneListTasksAfterTaskIDFlag, *controlPlaneListTasksLimitFlag, *controlPlaneListTasksSortOrderFlag) case "restore-database": endpoint = c.RestoreDatabase() data, err = controlplanec.BuildRestoreDatabasePayload(*controlPlaneRestoreDatabaseBodyFlag, *controlPlaneRestoreDatabaseDatabaseIDFlag, *controlPlaneRestoreDatabaseForceFlag) @@ -408,6 +459,10 @@ func controlPlaneUsage() { fmt.Fprintln(os.Stderr, ` list-database-tasks: Lists all tasks for a database.`) fmt.Fprintln(os.Stderr, ` get-database-task: Returns information about a particular task.`) fmt.Fprintln(os.Stderr, ` get-database-task-log: Returns the log of a particular task for a database.`) + fmt.Fprintln(os.Stderr, ` list-host-tasks: Lists all tasks for a host.`) + fmt.Fprintln(os.Stderr, ` get-host-task: Returns information about a particular task for a host.`) + fmt.Fprintln(os.Stderr, ` get-host-task-log: Returns the log of a particular task for a host.`) + fmt.Fprintln(os.Stderr, ` list-tasks: Lists tasks across all scopes with optional filtering by scope and entity ID.`) fmt.Fprintln(os.Stderr, ` restore-database: Perform an in-place restore of one or more nodes using the given restore configuration.`) fmt.Fprintln(os.Stderr, ` get-version: Returns version information for this Control Plane server.`) fmt.Fprintln(os.Stderr, ` restart-instance: Restarts a specific instance within a database. Supports immediate or scheduled restarts.`) @@ -788,6 +843,100 @@ func controlPlaneGetDatabaseTaskLogUsage() { fmt.Fprintf(os.Stderr, " %s %s\n", os.Args[0], "control-plane get-database-task-log --database-id \"76f9b8c0-4958-11f0-a489-3bb29577c696\" --task-id \"3c875a27-f6a6-4c1c-ba5f-6972fb1fc348\" --after-entry-id \"3c875a27-f6a6-4c1c-ba5f-6972fb1fc348\" --limit 100") } +func controlPlaneListHostTasksUsage() { + // Header with flags + fmt.Fprintf(os.Stderr, "%s [flags] control-plane list-host-tasks", os.Args[0]) + fmt.Fprint(os.Stderr, " -host-id STRING") + fmt.Fprint(os.Stderr, " -after-task-id STRING") + fmt.Fprint(os.Stderr, " -limit INT") + fmt.Fprint(os.Stderr, " -sort-order STRING") + fmt.Fprintln(os.Stderr) + + // Description + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, `Lists all tasks for a host.`) + + // Flags list + fmt.Fprintln(os.Stderr, ` -host-id STRING: ID of the host to list tasks for.`) + fmt.Fprintln(os.Stderr, ` -after-task-id STRING: `) + fmt.Fprintln(os.Stderr, ` -limit INT: `) + fmt.Fprintln(os.Stderr, ` -sort-order STRING: `) + + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Example:") + fmt.Fprintf(os.Stderr, " %s %s\n", os.Args[0], "control-plane list-host-tasks --host-id \"76f9b8c0-4958-11f0-a489-3bb29577c696\" --after-task-id \"3c875a27-f6a6-4c1c-ba5f-6972fb1fc348\" --limit 100 --sort-order \"ascend\"") +} + +func controlPlaneGetHostTaskUsage() { + // Header with flags + fmt.Fprintf(os.Stderr, "%s [flags] control-plane get-host-task", os.Args[0]) + fmt.Fprint(os.Stderr, " -host-id STRING") + fmt.Fprint(os.Stderr, " -task-id STRING") + fmt.Fprintln(os.Stderr) + + // Description + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, `Returns information about a particular task for a host.`) + + // Flags list + fmt.Fprintln(os.Stderr, ` -host-id STRING: ID of the host the task belongs to.`) + fmt.Fprintln(os.Stderr, ` -task-id STRING: ID of the task to get.`) + + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Example:") + fmt.Fprintf(os.Stderr, " %s %s\n", os.Args[0], "control-plane get-host-task --host-id \"76f9b8c0-4958-11f0-a489-3bb29577c696\" --task-id \"3c875a27-f6a6-4c1c-ba5f-6972fb1fc348\"") +} + +func controlPlaneGetHostTaskLogUsage() { + // Header with flags + fmt.Fprintf(os.Stderr, "%s [flags] control-plane get-host-task-log", os.Args[0]) + fmt.Fprint(os.Stderr, " -host-id STRING") + fmt.Fprint(os.Stderr, " -task-id STRING") + fmt.Fprint(os.Stderr, " -after-entry-id STRING") + fmt.Fprint(os.Stderr, " -limit INT") + fmt.Fprintln(os.Stderr) + + // Description + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, `Returns the log of a particular task for a host.`) + + // Flags list + fmt.Fprintln(os.Stderr, ` -host-id STRING: ID of the host to get the task logs for.`) + fmt.Fprintln(os.Stderr, ` -task-id STRING: ID of the task to get the logs for.`) + fmt.Fprintln(os.Stderr, ` -after-entry-id STRING: `) + fmt.Fprintln(os.Stderr, ` -limit INT: `) + + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Example:") + fmt.Fprintf(os.Stderr, " %s %s\n", os.Args[0], "control-plane get-host-task-log --host-id \"76f9b8c0-4958-11f0-a489-3bb29577c696\" --task-id \"3c875a27-f6a6-4c1c-ba5f-6972fb1fc348\" --after-entry-id \"3c875a27-f6a6-4c1c-ba5f-6972fb1fc348\" --limit 100") +} + +func controlPlaneListTasksUsage() { + // Header with flags + fmt.Fprintf(os.Stderr, "%s [flags] control-plane list-tasks", os.Args[0]) + fmt.Fprint(os.Stderr, " -scope STRING") + fmt.Fprint(os.Stderr, " -entity-id STRING") + fmt.Fprint(os.Stderr, " -after-task-id STRING") + fmt.Fprint(os.Stderr, " -limit INT") + fmt.Fprint(os.Stderr, " -sort-order STRING") + fmt.Fprintln(os.Stderr) + + // Description + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, `Lists tasks across all scopes with optional filtering by scope and entity ID.`) + + // Flags list + fmt.Fprintln(os.Stderr, ` -scope STRING: `) + fmt.Fprintln(os.Stderr, ` -entity-id STRING: `) + fmt.Fprintln(os.Stderr, ` -after-task-id STRING: `) + fmt.Fprintln(os.Stderr, ` -limit INT: `) + fmt.Fprintln(os.Stderr, ` -sort-order STRING: `) + + fmt.Fprintln(os.Stderr) + fmt.Fprintln(os.Stderr, "Example:") + fmt.Fprintf(os.Stderr, " %s %s\n", os.Args[0], "control-plane list-tasks --scope \"database\" --entity-id \"76f9b8c0-4958-11f0-a489-3bb29577c696\" --after-task-id \"3c875a27-f6a6-4c1c-ba5f-6972fb1fc348\" --limit 100 --sort-order \"ascend\"") +} + func controlPlaneRestoreDatabaseUsage() { // Header with flags fmt.Fprintf(os.Stderr, "%s [flags] control-plane restore-database", os.Args[0]) diff --git a/api/apiv1/gen/http/control_plane/client/cli.go b/api/apiv1/gen/http/control_plane/client/cli.go index a9e2b100..41eceae3 100644 --- a/api/apiv1/gen/http/control_plane/client/cli.go +++ b/api/apiv1/gen/http/control_plane/client/cli.go @@ -668,6 +668,232 @@ func BuildGetDatabaseTaskLogPayload(controlPlaneGetDatabaseTaskLogDatabaseID str return v, nil } +// BuildListHostTasksPayload builds the payload for the control-plane +// list-host-tasks endpoint from CLI flags. +func BuildListHostTasksPayload(controlPlaneListHostTasksHostID string, controlPlaneListHostTasksAfterTaskID string, controlPlaneListHostTasksLimit string, controlPlaneListHostTasksSortOrder string) (*controlplane.ListHostTasksPayload, error) { + var err error + var hostID string + { + hostID = controlPlaneListHostTasksHostID + if utf8.RuneCountInString(hostID) < 1 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 1, true)) + } + if utf8.RuneCountInString(hostID) > 63 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 63, false)) + } + if err != nil { + return nil, err + } + } + var afterTaskID *string + { + if controlPlaneListHostTasksAfterTaskID != "" { + afterTaskID = &controlPlaneListHostTasksAfterTaskID + err = goa.MergeErrors(err, goa.ValidateFormat("after_task_id", *afterTaskID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + } + var limit *int + { + if controlPlaneListHostTasksLimit != "" { + var v int64 + v, err = strconv.ParseInt(controlPlaneListHostTasksLimit, 10, strconv.IntSize) + val := int(v) + limit = &val + if err != nil { + return nil, fmt.Errorf("invalid value for limit, must be INT") + } + } + } + var sortOrder *string + { + if controlPlaneListHostTasksSortOrder != "" { + sortOrder = &controlPlaneListHostTasksSortOrder + if !(*sortOrder == "asc" || *sortOrder == "ascend" || *sortOrder == "ascending" || *sortOrder == "desc" || *sortOrder == "descend" || *sortOrder == "descending") { + err = goa.MergeErrors(err, goa.InvalidEnumValueError("sort_order", *sortOrder, []any{"asc", "ascend", "ascending", "desc", "descend", "descending"})) + } + if err != nil { + return nil, err + } + } + } + v := &controlplane.ListHostTasksPayload{} + v.HostID = controlplane.Identifier(hostID) + v.AfterTaskID = afterTaskID + v.Limit = limit + v.SortOrder = sortOrder + + return v, nil +} + +// BuildGetHostTaskPayload builds the payload for the control-plane +// get-host-task endpoint from CLI flags. +func BuildGetHostTaskPayload(controlPlaneGetHostTaskHostID string, controlPlaneGetHostTaskTaskID string) (*controlplane.GetHostTaskPayload, error) { + var err error + var hostID string + { + hostID = controlPlaneGetHostTaskHostID + if utf8.RuneCountInString(hostID) < 1 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 1, true)) + } + if utf8.RuneCountInString(hostID) > 63 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 63, false)) + } + if err != nil { + return nil, err + } + } + var taskID string + { + taskID = controlPlaneGetHostTaskTaskID + err = goa.MergeErrors(err, goa.ValidateFormat("task_id", taskID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + v := &controlplane.GetHostTaskPayload{} + v.HostID = controlplane.Identifier(hostID) + v.TaskID = taskID + + return v, nil +} + +// BuildGetHostTaskLogPayload builds the payload for the control-plane +// get-host-task-log endpoint from CLI flags. +func BuildGetHostTaskLogPayload(controlPlaneGetHostTaskLogHostID string, controlPlaneGetHostTaskLogTaskID string, controlPlaneGetHostTaskLogAfterEntryID string, controlPlaneGetHostTaskLogLimit string) (*controlplane.GetHostTaskLogPayload, error) { + var err error + var hostID string + { + hostID = controlPlaneGetHostTaskLogHostID + if utf8.RuneCountInString(hostID) < 1 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 1, true)) + } + if utf8.RuneCountInString(hostID) > 63 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 63, false)) + } + if err != nil { + return nil, err + } + } + var taskID string + { + taskID = controlPlaneGetHostTaskLogTaskID + err = goa.MergeErrors(err, goa.ValidateFormat("task_id", taskID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + var afterEntryID *string + { + if controlPlaneGetHostTaskLogAfterEntryID != "" { + afterEntryID = &controlPlaneGetHostTaskLogAfterEntryID + err = goa.MergeErrors(err, goa.ValidateFormat("after_entry_id", *afterEntryID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + } + var limit *int + { + if controlPlaneGetHostTaskLogLimit != "" { + var v int64 + v, err = strconv.ParseInt(controlPlaneGetHostTaskLogLimit, 10, strconv.IntSize) + val := int(v) + limit = &val + if err != nil { + return nil, fmt.Errorf("invalid value for limit, must be INT") + } + } + } + v := &controlplane.GetHostTaskLogPayload{} + v.HostID = controlplane.Identifier(hostID) + v.TaskID = taskID + v.AfterEntryID = afterEntryID + v.Limit = limit + + return v, nil +} + +// BuildListTasksPayload builds the payload for the control-plane list-tasks +// endpoint from CLI flags. +func BuildListTasksPayload(controlPlaneListTasksScope string, controlPlaneListTasksEntityID string, controlPlaneListTasksAfterTaskID string, controlPlaneListTasksLimit string, controlPlaneListTasksSortOrder string) (*controlplane.ListTasksPayload, error) { + var err error + var scope *string + { + if controlPlaneListTasksScope != "" { + scope = &controlPlaneListTasksScope + if !(*scope == "database" || *scope == "host") { + err = goa.MergeErrors(err, goa.InvalidEnumValueError("scope", *scope, []any{"database", "host"})) + } + if err != nil { + return nil, err + } + } + } + var entityID *string + { + if controlPlaneListTasksEntityID != "" { + entityID = &controlPlaneListTasksEntityID + if utf8.RuneCountInString(*entityID) < 1 { + err = goa.MergeErrors(err, goa.InvalidLengthError("entity_id", *entityID, utf8.RuneCountInString(*entityID), 1, true)) + } + if utf8.RuneCountInString(*entityID) > 63 { + err = goa.MergeErrors(err, goa.InvalidLengthError("entity_id", *entityID, utf8.RuneCountInString(*entityID), 63, false)) + } + if err != nil { + return nil, err + } + } + } + var afterTaskID *string + { + if controlPlaneListTasksAfterTaskID != "" { + afterTaskID = &controlPlaneListTasksAfterTaskID + err = goa.MergeErrors(err, goa.ValidateFormat("after_task_id", *afterTaskID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + } + var limit *int + { + if controlPlaneListTasksLimit != "" { + var v int64 + v, err = strconv.ParseInt(controlPlaneListTasksLimit, 10, strconv.IntSize) + val := int(v) + limit = &val + if err != nil { + return nil, fmt.Errorf("invalid value for limit, must be INT") + } + } + } + var sortOrder *string + { + if controlPlaneListTasksSortOrder != "" { + sortOrder = &controlPlaneListTasksSortOrder + if !(*sortOrder == "asc" || *sortOrder == "ascend" || *sortOrder == "ascending" || *sortOrder == "desc" || *sortOrder == "descend" || *sortOrder == "descending") { + err = goa.MergeErrors(err, goa.InvalidEnumValueError("sort_order", *sortOrder, []any{"asc", "ascend", "ascending", "desc", "descend", "descending"})) + } + if err != nil { + return nil, err + } + } + } + v := &controlplane.ListTasksPayload{} + v.Scope = scope + if entityID != nil { + tmpentityID := controlplane.Identifier(*entityID) + v.EntityID = &tmpentityID + } + v.AfterTaskID = afterTaskID + v.Limit = limit + v.SortOrder = sortOrder + + return v, nil +} + // BuildRestoreDatabasePayload builds the payload for the control-plane // restore-database endpoint from CLI flags. func BuildRestoreDatabasePayload(controlPlaneRestoreDatabaseBody string, controlPlaneRestoreDatabaseDatabaseID string, controlPlaneRestoreDatabaseForce string) (*controlplane.RestoreDatabasePayload, error) { diff --git a/api/apiv1/gen/http/control_plane/client/client.go b/api/apiv1/gen/http/control_plane/client/client.go index c4874cdc..743f2fc1 100644 --- a/api/apiv1/gen/http/control_plane/client/client.go +++ b/api/apiv1/gen/http/control_plane/client/client.go @@ -93,6 +93,22 @@ type Client struct { // get-database-task-log endpoint. GetDatabaseTaskLogDoer goahttp.Doer + // ListHostTasks Doer is the HTTP client used to make requests to the + // list-host-tasks endpoint. + ListHostTasksDoer goahttp.Doer + + // GetHostTask Doer is the HTTP client used to make requests to the + // get-host-task endpoint. + GetHostTaskDoer goahttp.Doer + + // GetHostTaskLog Doer is the HTTP client used to make requests to the + // get-host-task-log endpoint. + GetHostTaskLogDoer goahttp.Doer + + // ListTasks Doer is the HTTP client used to make requests to the list-tasks + // endpoint. + ListTasksDoer goahttp.Doer + // RestoreDatabase Doer is the HTTP client used to make requests to the // restore-database endpoint. RestoreDatabaseDoer goahttp.Doer @@ -157,6 +173,10 @@ func NewClient( ListDatabaseTasksDoer: doer, GetDatabaseTaskDoer: doer, GetDatabaseTaskLogDoer: doer, + ListHostTasksDoer: doer, + GetHostTaskDoer: doer, + GetHostTaskLogDoer: doer, + ListTasksDoer: doer, RestoreDatabaseDoer: doer, GetVersionDoer: doer, RestartInstanceDoer: doer, @@ -592,6 +612,97 @@ func (c *Client) GetDatabaseTaskLog() goa.Endpoint { } } +// ListHostTasks returns an endpoint that makes HTTP requests to the +// control-plane service list-host-tasks server. +func (c *Client) ListHostTasks() goa.Endpoint { + var ( + encodeRequest = EncodeListHostTasksRequest(c.encoder) + decodeResponse = DecodeListHostTasksResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildListHostTasksRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + resp, err := c.ListHostTasksDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("control-plane", "list-host-tasks", err) + } + return decodeResponse(resp) + } +} + +// GetHostTask returns an endpoint that makes HTTP requests to the +// control-plane service get-host-task server. +func (c *Client) GetHostTask() goa.Endpoint { + var ( + decodeResponse = DecodeGetHostTaskResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildGetHostTaskRequest(ctx, v) + if err != nil { + return nil, err + } + resp, err := c.GetHostTaskDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("control-plane", "get-host-task", err) + } + return decodeResponse(resp) + } +} + +// GetHostTaskLog returns an endpoint that makes HTTP requests to the +// control-plane service get-host-task-log server. +func (c *Client) GetHostTaskLog() goa.Endpoint { + var ( + encodeRequest = EncodeGetHostTaskLogRequest(c.encoder) + decodeResponse = DecodeGetHostTaskLogResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildGetHostTaskLogRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + resp, err := c.GetHostTaskLogDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("control-plane", "get-host-task-log", err) + } + return decodeResponse(resp) + } +} + +// ListTasks returns an endpoint that makes HTTP requests to the control-plane +// service list-tasks server. +func (c *Client) ListTasks() goa.Endpoint { + var ( + encodeRequest = EncodeListTasksRequest(c.encoder) + decodeResponse = DecodeListTasksResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildListTasksRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + resp, err := c.ListTasksDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("control-plane", "list-tasks", err) + } + return decodeResponse(resp) + } +} + // RestoreDatabase returns an endpoint that makes HTTP requests to the // control-plane service restore-database server. func (c *Client) RestoreDatabase() goa.Endpoint { diff --git a/api/apiv1/gen/http/control_plane/client/encode_decode.go b/api/apiv1/gen/http/control_plane/client/encode_decode.go index 55f13e3f..bbf3035d 100644 --- a/api/apiv1/gen/http/control_plane/client/encode_decode.go +++ b/api/apiv1/gen/http/control_plane/client/encode_decode.go @@ -2639,6 +2639,565 @@ func DecodeGetDatabaseTaskLogResponse(decoder func(*http.Response) goahttp.Decod } } +// BuildListHostTasksRequest instantiates a HTTP request object with method and +// path set to call the "control-plane" service "list-host-tasks" endpoint +func (c *Client) BuildListHostTasksRequest(ctx context.Context, v any) (*http.Request, error) { + var ( + hostID string + ) + { + p, ok := v.(*controlplane.ListHostTasksPayload) + if !ok { + return nil, goahttp.ErrInvalidType("control-plane", "list-host-tasks", "*controlplane.ListHostTasksPayload", v) + } + hostID = string(p.HostID) + } + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: ListHostTasksControlPlanePath(hostID)} + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("control-plane", "list-host-tasks", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeListHostTasksRequest returns an encoder for requests sent to the +// control-plane list-host-tasks server. +func EncodeListHostTasksRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { + return func(req *http.Request, v any) error { + p, ok := v.(*controlplane.ListHostTasksPayload) + if !ok { + return goahttp.ErrInvalidType("control-plane", "list-host-tasks", "*controlplane.ListHostTasksPayload", v) + } + values := req.URL.Query() + if p.AfterTaskID != nil { + values.Add("after_task_id", *p.AfterTaskID) + } + if p.Limit != nil { + values.Add("limit", fmt.Sprintf("%v", *p.Limit)) + } + if p.SortOrder != nil { + values.Add("sort_order", *p.SortOrder) + } + req.URL.RawQuery = values.Encode() + return nil + } +} + +// DecodeListHostTasksResponse returns a decoder for responses returned by the +// control-plane list-host-tasks endpoint. restoreBody controls whether the +// response body should be restored after having been read. +// DecodeListHostTasksResponse may return the following errors: +// - "cluster_not_initialized" (type *controlplane.APIError): http.StatusConflict +// - "invalid_input" (type *controlplane.APIError): http.StatusBadRequest +// - "not_found" (type *controlplane.APIError): http.StatusNotFound +// - "server_error" (type *controlplane.APIError): http.StatusInternalServerError +// - error: internal error +func DecodeListHostTasksResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body ListHostTasksResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-host-tasks", err) + } + err = ValidateListHostTasksResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-host-tasks", err) + } + res := NewListHostTasksResponseOK(&body) + return res, nil + case http.StatusConflict: + var ( + body ListHostTasksClusterNotInitializedResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-host-tasks", err) + } + err = ValidateListHostTasksClusterNotInitializedResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-host-tasks", err) + } + return nil, NewListHostTasksClusterNotInitialized(&body) + case http.StatusBadRequest: + var ( + body ListHostTasksInvalidInputResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-host-tasks", err) + } + err = ValidateListHostTasksInvalidInputResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-host-tasks", err) + } + return nil, NewListHostTasksInvalidInput(&body) + case http.StatusNotFound: + var ( + body ListHostTasksNotFoundResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-host-tasks", err) + } + err = ValidateListHostTasksNotFoundResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-host-tasks", err) + } + return nil, NewListHostTasksNotFound(&body) + case http.StatusInternalServerError: + var ( + body ListHostTasksServerErrorResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-host-tasks", err) + } + err = ValidateListHostTasksServerErrorResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-host-tasks", err) + } + return nil, NewListHostTasksServerError(&body) + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("control-plane", "list-host-tasks", resp.StatusCode, string(body)) + } + } +} + +// BuildGetHostTaskRequest instantiates a HTTP request object with method and +// path set to call the "control-plane" service "get-host-task" endpoint +func (c *Client) BuildGetHostTaskRequest(ctx context.Context, v any) (*http.Request, error) { + var ( + hostID string + taskID string + ) + { + p, ok := v.(*controlplane.GetHostTaskPayload) + if !ok { + return nil, goahttp.ErrInvalidType("control-plane", "get-host-task", "*controlplane.GetHostTaskPayload", v) + } + hostID = string(p.HostID) + taskID = p.TaskID + } + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: GetHostTaskControlPlanePath(hostID, taskID)} + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("control-plane", "get-host-task", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// DecodeGetHostTaskResponse returns a decoder for responses returned by the +// control-plane get-host-task endpoint. restoreBody controls whether the +// response body should be restored after having been read. +// DecodeGetHostTaskResponse may return the following errors: +// - "cluster_not_initialized" (type *controlplane.APIError): http.StatusConflict +// - "invalid_input" (type *controlplane.APIError): http.StatusBadRequest +// - "not_found" (type *controlplane.APIError): http.StatusNotFound +// - "server_error" (type *controlplane.APIError): http.StatusInternalServerError +// - error: internal error +func DecodeGetHostTaskResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body GetHostTaskResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task", err) + } + err = ValidateGetHostTaskResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task", err) + } + res := NewGetHostTaskTaskOK(&body) + return res, nil + case http.StatusConflict: + var ( + body GetHostTaskClusterNotInitializedResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task", err) + } + err = ValidateGetHostTaskClusterNotInitializedResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task", err) + } + return nil, NewGetHostTaskClusterNotInitialized(&body) + case http.StatusBadRequest: + var ( + body GetHostTaskInvalidInputResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task", err) + } + err = ValidateGetHostTaskInvalidInputResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task", err) + } + return nil, NewGetHostTaskInvalidInput(&body) + case http.StatusNotFound: + var ( + body GetHostTaskNotFoundResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task", err) + } + err = ValidateGetHostTaskNotFoundResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task", err) + } + return nil, NewGetHostTaskNotFound(&body) + case http.StatusInternalServerError: + var ( + body GetHostTaskServerErrorResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task", err) + } + err = ValidateGetHostTaskServerErrorResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task", err) + } + return nil, NewGetHostTaskServerError(&body) + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("control-plane", "get-host-task", resp.StatusCode, string(body)) + } + } +} + +// BuildGetHostTaskLogRequest instantiates a HTTP request object with method +// and path set to call the "control-plane" service "get-host-task-log" endpoint +func (c *Client) BuildGetHostTaskLogRequest(ctx context.Context, v any) (*http.Request, error) { + var ( + hostID string + taskID string + ) + { + p, ok := v.(*controlplane.GetHostTaskLogPayload) + if !ok { + return nil, goahttp.ErrInvalidType("control-plane", "get-host-task-log", "*controlplane.GetHostTaskLogPayload", v) + } + hostID = string(p.HostID) + taskID = p.TaskID + } + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: GetHostTaskLogControlPlanePath(hostID, taskID)} + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("control-plane", "get-host-task-log", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeGetHostTaskLogRequest returns an encoder for requests sent to the +// control-plane get-host-task-log server. +func EncodeGetHostTaskLogRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { + return func(req *http.Request, v any) error { + p, ok := v.(*controlplane.GetHostTaskLogPayload) + if !ok { + return goahttp.ErrInvalidType("control-plane", "get-host-task-log", "*controlplane.GetHostTaskLogPayload", v) + } + values := req.URL.Query() + if p.AfterEntryID != nil { + values.Add("after_entry_id", *p.AfterEntryID) + } + if p.Limit != nil { + values.Add("limit", fmt.Sprintf("%v", *p.Limit)) + } + req.URL.RawQuery = values.Encode() + return nil + } +} + +// DecodeGetHostTaskLogResponse returns a decoder for responses returned by the +// control-plane get-host-task-log endpoint. restoreBody controls whether the +// response body should be restored after having been read. +// DecodeGetHostTaskLogResponse may return the following errors: +// - "cluster_not_initialized" (type *controlplane.APIError): http.StatusConflict +// - "invalid_input" (type *controlplane.APIError): http.StatusBadRequest +// - "not_found" (type *controlplane.APIError): http.StatusNotFound +// - "server_error" (type *controlplane.APIError): http.StatusInternalServerError +// - error: internal error +func DecodeGetHostTaskLogResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body GetHostTaskLogResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task-log", err) + } + err = ValidateGetHostTaskLogResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task-log", err) + } + res := NewGetHostTaskLogTaskLogOK(&body) + return res, nil + case http.StatusConflict: + var ( + body GetHostTaskLogClusterNotInitializedResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task-log", err) + } + err = ValidateGetHostTaskLogClusterNotInitializedResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task-log", err) + } + return nil, NewGetHostTaskLogClusterNotInitialized(&body) + case http.StatusBadRequest: + var ( + body GetHostTaskLogInvalidInputResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task-log", err) + } + err = ValidateGetHostTaskLogInvalidInputResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task-log", err) + } + return nil, NewGetHostTaskLogInvalidInput(&body) + case http.StatusNotFound: + var ( + body GetHostTaskLogNotFoundResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task-log", err) + } + err = ValidateGetHostTaskLogNotFoundResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task-log", err) + } + return nil, NewGetHostTaskLogNotFound(&body) + case http.StatusInternalServerError: + var ( + body GetHostTaskLogServerErrorResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "get-host-task-log", err) + } + err = ValidateGetHostTaskLogServerErrorResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "get-host-task-log", err) + } + return nil, NewGetHostTaskLogServerError(&body) + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("control-plane", "get-host-task-log", resp.StatusCode, string(body)) + } + } +} + +// BuildListTasksRequest instantiates a HTTP request object with method and +// path set to call the "control-plane" service "list-tasks" endpoint +func (c *Client) BuildListTasksRequest(ctx context.Context, v any) (*http.Request, error) { + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: ListTasksControlPlanePath()} + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("control-plane", "list-tasks", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeListTasksRequest returns an encoder for requests sent to the +// control-plane list-tasks server. +func EncodeListTasksRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { + return func(req *http.Request, v any) error { + p, ok := v.(*controlplane.ListTasksPayload) + if !ok { + return goahttp.ErrInvalidType("control-plane", "list-tasks", "*controlplane.ListTasksPayload", v) + } + values := req.URL.Query() + if p.Scope != nil { + values.Add("scope", *p.Scope) + } + if p.EntityID != nil { + values.Add("entity_id", string(*p.EntityID)) + } + if p.AfterTaskID != nil { + values.Add("after_task_id", *p.AfterTaskID) + } + if p.Limit != nil { + values.Add("limit", fmt.Sprintf("%v", *p.Limit)) + } + if p.SortOrder != nil { + values.Add("sort_order", *p.SortOrder) + } + req.URL.RawQuery = values.Encode() + return nil + } +} + +// DecodeListTasksResponse returns a decoder for responses returned by the +// control-plane list-tasks endpoint. restoreBody controls whether the response +// body should be restored after having been read. +// DecodeListTasksResponse may return the following errors: +// - "cluster_not_initialized" (type *controlplane.APIError): http.StatusConflict +// - "invalid_input" (type *controlplane.APIError): http.StatusBadRequest +// - "server_error" (type *controlplane.APIError): http.StatusInternalServerError +// - error: internal error +func DecodeListTasksResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body ListTasksResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-tasks", err) + } + err = ValidateListTasksResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-tasks", err) + } + res := NewListTasksResponseOK(&body) + return res, nil + case http.StatusConflict: + var ( + body ListTasksClusterNotInitializedResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-tasks", err) + } + err = ValidateListTasksClusterNotInitializedResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-tasks", err) + } + return nil, NewListTasksClusterNotInitialized(&body) + case http.StatusBadRequest: + var ( + body ListTasksInvalidInputResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-tasks", err) + } + err = ValidateListTasksInvalidInputResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-tasks", err) + } + return nil, NewListTasksInvalidInput(&body) + case http.StatusInternalServerError: + var ( + body ListTasksServerErrorResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("control-plane", "list-tasks", err) + } + err = ValidateListTasksServerErrorResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("control-plane", "list-tasks", err) + } + return nil, NewListTasksServerError(&body) + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("control-plane", "list-tasks", resp.StatusCode, string(body)) + } + } +} + // BuildRestoreDatabaseRequest instantiates a HTTP request object with method // and path set to call the "control-plane" service "restore-database" endpoint func (c *Client) BuildRestoreDatabaseRequest(ctx context.Context, v any) (*http.Request, error) { diff --git a/api/apiv1/gen/http/control_plane/client/paths.go b/api/apiv1/gen/http/control_plane/client/paths.go index c29dddf5..5ba5ea79 100644 --- a/api/apiv1/gen/http/control_plane/client/paths.go +++ b/api/apiv1/gen/http/control_plane/client/paths.go @@ -106,6 +106,26 @@ func GetDatabaseTaskLogControlPlanePath(databaseID string, taskID string) string return fmt.Sprintf("/v1/databases/%v/tasks/%v/log", databaseID, taskID) } +// ListHostTasksControlPlanePath returns the URL path to the control-plane service list-host-tasks HTTP endpoint. +func ListHostTasksControlPlanePath(hostID string) string { + return fmt.Sprintf("/v1/hosts/%v/tasks", hostID) +} + +// GetHostTaskControlPlanePath returns the URL path to the control-plane service get-host-task HTTP endpoint. +func GetHostTaskControlPlanePath(hostID string, taskID string) string { + return fmt.Sprintf("/v1/hosts/%v/tasks/%v", hostID, taskID) +} + +// GetHostTaskLogControlPlanePath returns the URL path to the control-plane service get-host-task-log HTTP endpoint. +func GetHostTaskLogControlPlanePath(hostID string, taskID string) string { + return fmt.Sprintf("/v1/hosts/%v/tasks/%v/logs", hostID, taskID) +} + +// ListTasksControlPlanePath returns the URL path to the control-plane service list-tasks HTTP endpoint. +func ListTasksControlPlanePath() string { + return "/v1/tasks" +} + // RestoreDatabaseControlPlanePath returns the URL path to the control-plane service restore-database HTTP endpoint. func RestoreDatabaseControlPlanePath(databaseID string) string { return fmt.Sprintf("/v1/databases/%v/restore", databaseID) diff --git a/api/apiv1/gen/http/control_plane/client/types.go b/api/apiv1/gen/http/control_plane/client/types.go index b52a9edc..703f4710 100644 --- a/api/apiv1/gen/http/control_plane/client/types.go +++ b/api/apiv1/gen/http/control_plane/client/types.go @@ -306,6 +306,68 @@ type GetDatabaseTaskLogResponseBody struct { Entries []*TaskLogEntryResponseBody `form:"entries,omitempty" json:"entries,omitempty" xml:"entries,omitempty"` } +// ListHostTasksResponseBody is the type of the "control-plane" service +// "list-host-tasks" endpoint HTTP response body. +type ListHostTasksResponseBody struct { + Tasks []*TaskResponseBody `form:"tasks,omitempty" json:"tasks,omitempty" xml:"tasks,omitempty"` +} + +// GetHostTaskResponseBody is the type of the "control-plane" service +// "get-host-task" endpoint HTTP response body. +type GetHostTaskResponseBody struct { + // The parent task ID of the task. + ParentID *string `form:"parent_id,omitempty" json:"parent_id,omitempty" xml:"parent_id,omitempty"` + // The scope of the task (database or host). + Scope *string `form:"scope,omitempty" json:"scope,omitempty" xml:"scope,omitempty"` + // The entity ID (database_id or host_id) that this task belongs to. + EntityID *string `form:"entity_id,omitempty" json:"entity_id,omitempty" xml:"entity_id,omitempty"` + // The database ID of the task. + DatabaseID *string `form:"database_id,omitempty" json:"database_id,omitempty" xml:"database_id,omitempty"` + // The name of the node that the task is operating on. + NodeName *string `form:"node_name,omitempty" json:"node_name,omitempty" xml:"node_name,omitempty"` + // The ID of the instance that the task is operating on. + InstanceID *string `form:"instance_id,omitempty" json:"instance_id,omitempty" xml:"instance_id,omitempty"` + // The ID of the host that the task is running on. + HostID *string `form:"host_id,omitempty" json:"host_id,omitempty" xml:"host_id,omitempty"` + // The unique ID of the task. + TaskID *string `form:"task_id,omitempty" json:"task_id,omitempty" xml:"task_id,omitempty"` + // The time when the task was created. + CreatedAt *string `form:"created_at,omitempty" json:"created_at,omitempty" xml:"created_at,omitempty"` + // The time when the task was completed. + CompletedAt *string `form:"completed_at,omitempty" json:"completed_at,omitempty" xml:"completed_at,omitempty"` + // The type of the task. + Type *string `form:"type,omitempty" json:"type,omitempty" xml:"type,omitempty"` + // The status of the task. + Status *string `form:"status,omitempty" json:"status,omitempty" xml:"status,omitempty"` + // The error message if the task failed. + Error *string `form:"error,omitempty" json:"error,omitempty" xml:"error,omitempty"` +} + +// GetHostTaskLogResponseBody is the type of the "control-plane" service +// "get-host-task-log" endpoint HTTP response body. +type GetHostTaskLogResponseBody struct { + // The scope of the task (database or host). + Scope *string `form:"scope,omitempty" json:"scope,omitempty" xml:"scope,omitempty"` + // The entity ID (database_id or host_id) that this task log belongs to. + EntityID *string `form:"entity_id,omitempty" json:"entity_id,omitempty" xml:"entity_id,omitempty"` + // The database ID of the task log. Deprecated: use entity_id instead. + DatabaseID *string `form:"database_id,omitempty" json:"database_id,omitempty" xml:"database_id,omitempty"` + // The unique ID of the task log. + TaskID *string `form:"task_id,omitempty" json:"task_id,omitempty" xml:"task_id,omitempty"` + // The status of the task. + TaskStatus *string `form:"task_status,omitempty" json:"task_status,omitempty" xml:"task_status,omitempty"` + // The ID of the last entry in the task log. + LastEntryID *string `form:"last_entry_id,omitempty" json:"last_entry_id,omitempty" xml:"last_entry_id,omitempty"` + // Entries in the task log. + Entries []*TaskLogEntryResponseBody `form:"entries,omitempty" json:"entries,omitempty" xml:"entries,omitempty"` +} + +// ListTasksResponseBody is the type of the "control-plane" service +// "list-tasks" endpoint HTTP response body. +type ListTasksResponseBody struct { + Tasks []*TaskResponseBody `form:"tasks,omitempty" json:"tasks,omitempty" xml:"tasks,omitempty"` +} + // RestoreDatabaseResponseBody is the type of the "control-plane" service // "restore-database" endpoint HTTP response body. type RestoreDatabaseResponseBody struct { @@ -1154,6 +1216,152 @@ type GetDatabaseTaskLogServerErrorResponseBody struct { Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` } +// ListHostTasksClusterNotInitializedResponseBody is the type of the +// "control-plane" service "list-host-tasks" endpoint HTTP response body for +// the "cluster_not_initialized" error. +type ListHostTasksClusterNotInitializedResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// ListHostTasksInvalidInputResponseBody is the type of the "control-plane" +// service "list-host-tasks" endpoint HTTP response body for the +// "invalid_input" error. +type ListHostTasksInvalidInputResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// ListHostTasksNotFoundResponseBody is the type of the "control-plane" service +// "list-host-tasks" endpoint HTTP response body for the "not_found" error. +type ListHostTasksNotFoundResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// ListHostTasksServerErrorResponseBody is the type of the "control-plane" +// service "list-host-tasks" endpoint HTTP response body for the "server_error" +// error. +type ListHostTasksServerErrorResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// GetHostTaskClusterNotInitializedResponseBody is the type of the +// "control-plane" service "get-host-task" endpoint HTTP response body for the +// "cluster_not_initialized" error. +type GetHostTaskClusterNotInitializedResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// GetHostTaskInvalidInputResponseBody is the type of the "control-plane" +// service "get-host-task" endpoint HTTP response body for the "invalid_input" +// error. +type GetHostTaskInvalidInputResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// GetHostTaskNotFoundResponseBody is the type of the "control-plane" service +// "get-host-task" endpoint HTTP response body for the "not_found" error. +type GetHostTaskNotFoundResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// GetHostTaskServerErrorResponseBody is the type of the "control-plane" +// service "get-host-task" endpoint HTTP response body for the "server_error" +// error. +type GetHostTaskServerErrorResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// GetHostTaskLogClusterNotInitializedResponseBody is the type of the +// "control-plane" service "get-host-task-log" endpoint HTTP response body for +// the "cluster_not_initialized" error. +type GetHostTaskLogClusterNotInitializedResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// GetHostTaskLogInvalidInputResponseBody is the type of the "control-plane" +// service "get-host-task-log" endpoint HTTP response body for the +// "invalid_input" error. +type GetHostTaskLogInvalidInputResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// GetHostTaskLogNotFoundResponseBody is the type of the "control-plane" +// service "get-host-task-log" endpoint HTTP response body for the "not_found" +// error. +type GetHostTaskLogNotFoundResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// GetHostTaskLogServerErrorResponseBody is the type of the "control-plane" +// service "get-host-task-log" endpoint HTTP response body for the +// "server_error" error. +type GetHostTaskLogServerErrorResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// ListTasksClusterNotInitializedResponseBody is the type of the +// "control-plane" service "list-tasks" endpoint HTTP response body for the +// "cluster_not_initialized" error. +type ListTasksClusterNotInitializedResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// ListTasksInvalidInputResponseBody is the type of the "control-plane" service +// "list-tasks" endpoint HTTP response body for the "invalid_input" error. +type ListTasksInvalidInputResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + +// ListTasksServerErrorResponseBody is the type of the "control-plane" service +// "list-tasks" endpoint HTTP response body for the "server_error" error. +type ListTasksServerErrorResponseBody struct { + // The name of the error. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // The error message. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` +} + // RestoreDatabaseClusterNotInitializedResponseBody is the type of the // "control-plane" service "restore-database" endpoint HTTP response body for // the "cluster_not_initialized" error. @@ -3686,6 +3894,252 @@ func NewGetDatabaseTaskLogServerError(body *GetDatabaseTaskLogServerErrorRespons return v } +// NewListHostTasksResponseOK builds a "control-plane" service +// "list-host-tasks" endpoint result from a HTTP "OK" response. +func NewListHostTasksResponseOK(body *ListHostTasksResponseBody) *controlplane.ListHostTasksResponse { + v := &controlplane.ListHostTasksResponse{} + if body.Tasks != nil { + v.Tasks = make([]*controlplane.Task, len(body.Tasks)) + for i, val := range body.Tasks { + if val == nil { + v.Tasks[i] = nil + continue + } + v.Tasks[i] = unmarshalTaskResponseBodyToControlplaneTask(val) + } + } + + return v +} + +// NewListHostTasksClusterNotInitialized builds a control-plane service +// list-host-tasks endpoint cluster_not_initialized error. +func NewListHostTasksClusterNotInitialized(body *ListHostTasksClusterNotInitializedResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewListHostTasksInvalidInput builds a control-plane service list-host-tasks +// endpoint invalid_input error. +func NewListHostTasksInvalidInput(body *ListHostTasksInvalidInputResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewListHostTasksNotFound builds a control-plane service list-host-tasks +// endpoint not_found error. +func NewListHostTasksNotFound(body *ListHostTasksNotFoundResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewListHostTasksServerError builds a control-plane service list-host-tasks +// endpoint server_error error. +func NewListHostTasksServerError(body *ListHostTasksServerErrorResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewGetHostTaskTaskOK builds a "control-plane" service "get-host-task" +// endpoint result from a HTTP "OK" response. +func NewGetHostTaskTaskOK(body *GetHostTaskResponseBody) *controlplane.Task { + v := &controlplane.Task{ + ParentID: body.ParentID, + Scope: *body.Scope, + EntityID: *body.EntityID, + DatabaseID: body.DatabaseID, + NodeName: body.NodeName, + InstanceID: body.InstanceID, + HostID: body.HostID, + TaskID: *body.TaskID, + CreatedAt: *body.CreatedAt, + CompletedAt: body.CompletedAt, + Type: *body.Type, + Status: *body.Status, + Error: body.Error, + } + + return v +} + +// NewGetHostTaskClusterNotInitialized builds a control-plane service +// get-host-task endpoint cluster_not_initialized error. +func NewGetHostTaskClusterNotInitialized(body *GetHostTaskClusterNotInitializedResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewGetHostTaskInvalidInput builds a control-plane service get-host-task +// endpoint invalid_input error. +func NewGetHostTaskInvalidInput(body *GetHostTaskInvalidInputResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewGetHostTaskNotFound builds a control-plane service get-host-task endpoint +// not_found error. +func NewGetHostTaskNotFound(body *GetHostTaskNotFoundResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewGetHostTaskServerError builds a control-plane service get-host-task +// endpoint server_error error. +func NewGetHostTaskServerError(body *GetHostTaskServerErrorResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewGetHostTaskLogTaskLogOK builds a "control-plane" service +// "get-host-task-log" endpoint result from a HTTP "OK" response. +func NewGetHostTaskLogTaskLogOK(body *GetHostTaskLogResponseBody) *controlplane.TaskLog { + v := &controlplane.TaskLog{ + Scope: *body.Scope, + EntityID: *body.EntityID, + DatabaseID: body.DatabaseID, + TaskID: *body.TaskID, + TaskStatus: *body.TaskStatus, + LastEntryID: body.LastEntryID, + } + v.Entries = make([]*controlplane.TaskLogEntry, len(body.Entries)) + for i, val := range body.Entries { + if val == nil { + v.Entries[i] = nil + continue + } + v.Entries[i] = unmarshalTaskLogEntryResponseBodyToControlplaneTaskLogEntry(val) + } + + return v +} + +// NewGetHostTaskLogClusterNotInitialized builds a control-plane service +// get-host-task-log endpoint cluster_not_initialized error. +func NewGetHostTaskLogClusterNotInitialized(body *GetHostTaskLogClusterNotInitializedResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewGetHostTaskLogInvalidInput builds a control-plane service +// get-host-task-log endpoint invalid_input error. +func NewGetHostTaskLogInvalidInput(body *GetHostTaskLogInvalidInputResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewGetHostTaskLogNotFound builds a control-plane service get-host-task-log +// endpoint not_found error. +func NewGetHostTaskLogNotFound(body *GetHostTaskLogNotFoundResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewGetHostTaskLogServerError builds a control-plane service +// get-host-task-log endpoint server_error error. +func NewGetHostTaskLogServerError(body *GetHostTaskLogServerErrorResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewListTasksResponseOK builds a "control-plane" service "list-tasks" +// endpoint result from a HTTP "OK" response. +func NewListTasksResponseOK(body *ListTasksResponseBody) *controlplane.ListTasksResponse { + v := &controlplane.ListTasksResponse{} + if body.Tasks != nil { + v.Tasks = make([]*controlplane.Task, len(body.Tasks)) + for i, val := range body.Tasks { + if val == nil { + v.Tasks[i] = nil + continue + } + v.Tasks[i] = unmarshalTaskResponseBodyToControlplaneTask(val) + } + } + + return v +} + +// NewListTasksClusterNotInitialized builds a control-plane service list-tasks +// endpoint cluster_not_initialized error. +func NewListTasksClusterNotInitialized(body *ListTasksClusterNotInitializedResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewListTasksInvalidInput builds a control-plane service list-tasks endpoint +// invalid_input error. +func NewListTasksInvalidInput(body *ListTasksInvalidInputResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + +// NewListTasksServerError builds a control-plane service list-tasks endpoint +// server_error error. +func NewListTasksServerError(body *ListTasksServerErrorResponseBody) *controlplane.APIError { + v := &controlplane.APIError{ + Name: *body.Name, + Message: *body.Message, + } + + return v +} + // NewRestoreDatabaseResponseOK builds a "control-plane" service // "restore-database" endpoint result from a HTTP "OK" response. func NewRestoreDatabaseResponseOK(body *RestoreDatabaseResponseBody) *controlplane.RestoreDatabaseResponse { @@ -4103,6 +4557,30 @@ func ValidateGetDatabaseTaskLogResponseBody(body *GetDatabaseTaskLogResponseBody return } +// ValidateListHostTasksResponseBody runs a no-op validation on +// List-Host-TasksResponseBody +func ValidateListHostTasksResponseBody(body *ListHostTasksResponseBody) (err error) { + return +} + +// ValidateGetHostTaskResponseBody runs a no-op validation on +// Get-Host-TaskResponseBody +func ValidateGetHostTaskResponseBody(body *GetHostTaskResponseBody) (err error) { + return +} + +// ValidateGetHostTaskLogResponseBody runs a no-op validation on +// Get-Host-Task-LogResponseBody +func ValidateGetHostTaskLogResponseBody(body *GetHostTaskLogResponseBody) (err error) { + return +} + +// ValidateListTasksResponseBody runs a no-op validation on +// List-TasksResponseBody +func ValidateListTasksResponseBody(body *ListTasksResponseBody) (err error) { + return +} + // ValidateRestoreDatabaseResponseBody runs a no-op validation on // Restore-DatabaseResponseBody func ValidateRestoreDatabaseResponseBody(body *RestoreDatabaseResponseBody) (err error) { @@ -4610,6 +5088,96 @@ func ValidateGetDatabaseTaskLogServerErrorResponseBody(body *GetDatabaseTaskLogS return } +// ValidateListHostTasksClusterNotInitializedResponseBody runs a no-op +// validation on list-host-tasks_cluster_not_initialized_response_body +func ValidateListHostTasksClusterNotInitializedResponseBody(body *ListHostTasksClusterNotInitializedResponseBody) (err error) { + return +} + +// ValidateListHostTasksInvalidInputResponseBody runs a no-op validation on +// list-host-tasks_invalid_input_response_body +func ValidateListHostTasksInvalidInputResponseBody(body *ListHostTasksInvalidInputResponseBody) (err error) { + return +} + +// ValidateListHostTasksNotFoundResponseBody runs a no-op validation on +// list-host-tasks_not_found_response_body +func ValidateListHostTasksNotFoundResponseBody(body *ListHostTasksNotFoundResponseBody) (err error) { + return +} + +// ValidateListHostTasksServerErrorResponseBody runs a no-op validation on +// list-host-tasks_server_error_response_body +func ValidateListHostTasksServerErrorResponseBody(body *ListHostTasksServerErrorResponseBody) (err error) { + return +} + +// ValidateGetHostTaskClusterNotInitializedResponseBody runs a no-op validation +// on get-host-task_cluster_not_initialized_response_body +func ValidateGetHostTaskClusterNotInitializedResponseBody(body *GetHostTaskClusterNotInitializedResponseBody) (err error) { + return +} + +// ValidateGetHostTaskInvalidInputResponseBody runs a no-op validation on +// get-host-task_invalid_input_response_body +func ValidateGetHostTaskInvalidInputResponseBody(body *GetHostTaskInvalidInputResponseBody) (err error) { + return +} + +// ValidateGetHostTaskNotFoundResponseBody runs a no-op validation on +// get-host-task_not_found_response_body +func ValidateGetHostTaskNotFoundResponseBody(body *GetHostTaskNotFoundResponseBody) (err error) { + return +} + +// ValidateGetHostTaskServerErrorResponseBody runs a no-op validation on +// get-host-task_server_error_response_body +func ValidateGetHostTaskServerErrorResponseBody(body *GetHostTaskServerErrorResponseBody) (err error) { + return +} + +// ValidateGetHostTaskLogClusterNotInitializedResponseBody runs a no-op +// validation on get-host-task-log_cluster_not_initialized_response_body +func ValidateGetHostTaskLogClusterNotInitializedResponseBody(body *GetHostTaskLogClusterNotInitializedResponseBody) (err error) { + return +} + +// ValidateGetHostTaskLogInvalidInputResponseBody runs a no-op validation on +// get-host-task-log_invalid_input_response_body +func ValidateGetHostTaskLogInvalidInputResponseBody(body *GetHostTaskLogInvalidInputResponseBody) (err error) { + return +} + +// ValidateGetHostTaskLogNotFoundResponseBody runs a no-op validation on +// get-host-task-log_not_found_response_body +func ValidateGetHostTaskLogNotFoundResponseBody(body *GetHostTaskLogNotFoundResponseBody) (err error) { + return +} + +// ValidateGetHostTaskLogServerErrorResponseBody runs a no-op validation on +// get-host-task-log_server_error_response_body +func ValidateGetHostTaskLogServerErrorResponseBody(body *GetHostTaskLogServerErrorResponseBody) (err error) { + return +} + +// ValidateListTasksClusterNotInitializedResponseBody runs a no-op validation +// on list-tasks_cluster_not_initialized_response_body +func ValidateListTasksClusterNotInitializedResponseBody(body *ListTasksClusterNotInitializedResponseBody) (err error) { + return +} + +// ValidateListTasksInvalidInputResponseBody runs a no-op validation on +// list-tasks_invalid_input_response_body +func ValidateListTasksInvalidInputResponseBody(body *ListTasksInvalidInputResponseBody) (err error) { + return +} + +// ValidateListTasksServerErrorResponseBody runs a no-op validation on +// list-tasks_server_error_response_body +func ValidateListTasksServerErrorResponseBody(body *ListTasksServerErrorResponseBody) (err error) { + return +} + // ValidateRestoreDatabaseClusterNotInitializedResponseBody runs a no-op // validation on restore-database_cluster_not_initialized_response_body func ValidateRestoreDatabaseClusterNotInitializedResponseBody(body *RestoreDatabaseClusterNotInitializedResponseBody) (err error) { diff --git a/api/apiv1/gen/http/control_plane/server/encode_decode.go b/api/apiv1/gen/http/control_plane/server/encode_decode.go index f16b92b2..75a46c07 100644 --- a/api/apiv1/gen/http/control_plane/server/encode_decode.go +++ b/api/apiv1/gen/http/control_plane/server/encode_decode.go @@ -2151,6 +2151,521 @@ func EncodeGetDatabaseTaskLogError(encoder func(context.Context, http.ResponseWr } } +// EncodeListHostTasksResponse returns an encoder for responses returned by the +// control-plane list-host-tasks endpoint. +func EncodeListHostTasksResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { + return func(ctx context.Context, w http.ResponseWriter, v any) error { + res, _ := v.(*controlplane.ListHostTasksResponse) + enc := encoder(ctx, w) + body := NewListHostTasksResponseBody(res) + w.WriteHeader(http.StatusOK) + return enc.Encode(body) + } +} + +// DecodeListHostTasksRequest returns a decoder for requests sent to the +// control-plane list-host-tasks endpoint. +func DecodeListHostTasksRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (*controlplane.ListHostTasksPayload, error) { + return func(r *http.Request) (*controlplane.ListHostTasksPayload, error) { + var ( + hostID string + afterTaskID *string + limit *int + sortOrder *string + err error + + params = mux.Vars(r) + ) + hostID = params["host_id"] + if utf8.RuneCountInString(hostID) < 1 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 1, true)) + } + if utf8.RuneCountInString(hostID) > 63 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 63, false)) + } + qp := r.URL.Query() + afterTaskIDRaw := qp.Get("after_task_id") + if afterTaskIDRaw != "" { + afterTaskID = &afterTaskIDRaw + } + if afterTaskID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("after_task_id", *afterTaskID, goa.FormatUUID)) + } + { + limitRaw := qp.Get("limit") + if limitRaw != "" { + v, err2 := strconv.ParseInt(limitRaw, 10, strconv.IntSize) + if err2 != nil { + err = goa.MergeErrors(err, goa.InvalidFieldTypeError("limit", limitRaw, "integer")) + } + pv := int(v) + limit = &pv + } + } + sortOrderRaw := qp.Get("sort_order") + if sortOrderRaw != "" { + sortOrder = &sortOrderRaw + } + if sortOrder != nil { + if !(*sortOrder == "asc" || *sortOrder == "ascend" || *sortOrder == "ascending" || *sortOrder == "desc" || *sortOrder == "descend" || *sortOrder == "descending") { + err = goa.MergeErrors(err, goa.InvalidEnumValueError("sort_order", *sortOrder, []any{"asc", "ascend", "ascending", "desc", "descend", "descending"})) + } + } + if err != nil { + return nil, err + } + payload := NewListHostTasksPayload(hostID, afterTaskID, limit, sortOrder) + + return payload, nil + } +} + +// EncodeListHostTasksError returns an encoder for errors returned by the +// list-host-tasks control-plane endpoint. +func EncodeListHostTasksError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error { + encodeError := goahttp.ErrorEncoder(encoder, formatter) + return func(ctx context.Context, w http.ResponseWriter, v error) error { + var en goa.GoaErrorNamer + if !errors.As(v, &en) { + return encodeError(ctx, w, v) + } + switch en.GoaErrorName() { + case "cluster_not_initialized": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewListHostTasksClusterNotInitializedResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusConflict) + return enc.Encode(body) + case "invalid_input": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewListHostTasksInvalidInputResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusBadRequest) + return enc.Encode(body) + case "not_found": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewListHostTasksNotFoundResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusNotFound) + return enc.Encode(body) + case "server_error": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewListHostTasksServerErrorResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusInternalServerError) + return enc.Encode(body) + default: + return encodeError(ctx, w, v) + } + } +} + +// EncodeGetHostTaskResponse returns an encoder for responses returned by the +// control-plane get-host-task endpoint. +func EncodeGetHostTaskResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { + return func(ctx context.Context, w http.ResponseWriter, v any) error { + res, _ := v.(*controlplane.Task) + enc := encoder(ctx, w) + body := NewGetHostTaskResponseBody(res) + w.WriteHeader(http.StatusOK) + return enc.Encode(body) + } +} + +// DecodeGetHostTaskRequest returns a decoder for requests sent to the +// control-plane get-host-task endpoint. +func DecodeGetHostTaskRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (*controlplane.GetHostTaskPayload, error) { + return func(r *http.Request) (*controlplane.GetHostTaskPayload, error) { + var ( + hostID string + taskID string + err error + + params = mux.Vars(r) + ) + hostID = params["host_id"] + if utf8.RuneCountInString(hostID) < 1 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 1, true)) + } + if utf8.RuneCountInString(hostID) > 63 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 63, false)) + } + taskID = params["task_id"] + err = goa.MergeErrors(err, goa.ValidateFormat("task_id", taskID, goa.FormatUUID)) + if err != nil { + return nil, err + } + payload := NewGetHostTaskPayload(hostID, taskID) + + return payload, nil + } +} + +// EncodeGetHostTaskError returns an encoder for errors returned by the +// get-host-task control-plane endpoint. +func EncodeGetHostTaskError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error { + encodeError := goahttp.ErrorEncoder(encoder, formatter) + return func(ctx context.Context, w http.ResponseWriter, v error) error { + var en goa.GoaErrorNamer + if !errors.As(v, &en) { + return encodeError(ctx, w, v) + } + switch en.GoaErrorName() { + case "cluster_not_initialized": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetHostTaskClusterNotInitializedResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusConflict) + return enc.Encode(body) + case "invalid_input": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetHostTaskInvalidInputResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusBadRequest) + return enc.Encode(body) + case "not_found": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetHostTaskNotFoundResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusNotFound) + return enc.Encode(body) + case "server_error": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetHostTaskServerErrorResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusInternalServerError) + return enc.Encode(body) + default: + return encodeError(ctx, w, v) + } + } +} + +// EncodeGetHostTaskLogResponse returns an encoder for responses returned by +// the control-plane get-host-task-log endpoint. +func EncodeGetHostTaskLogResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { + return func(ctx context.Context, w http.ResponseWriter, v any) error { + res, _ := v.(*controlplane.TaskLog) + enc := encoder(ctx, w) + body := NewGetHostTaskLogResponseBody(res) + w.WriteHeader(http.StatusOK) + return enc.Encode(body) + } +} + +// DecodeGetHostTaskLogRequest returns a decoder for requests sent to the +// control-plane get-host-task-log endpoint. +func DecodeGetHostTaskLogRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (*controlplane.GetHostTaskLogPayload, error) { + return func(r *http.Request) (*controlplane.GetHostTaskLogPayload, error) { + var ( + hostID string + taskID string + afterEntryID *string + limit *int + err error + + params = mux.Vars(r) + ) + hostID = params["host_id"] + if utf8.RuneCountInString(hostID) < 1 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 1, true)) + } + if utf8.RuneCountInString(hostID) > 63 { + err = goa.MergeErrors(err, goa.InvalidLengthError("host_id", hostID, utf8.RuneCountInString(hostID), 63, false)) + } + taskID = params["task_id"] + err = goa.MergeErrors(err, goa.ValidateFormat("task_id", taskID, goa.FormatUUID)) + qp := r.URL.Query() + afterEntryIDRaw := qp.Get("after_entry_id") + if afterEntryIDRaw != "" { + afterEntryID = &afterEntryIDRaw + } + if afterEntryID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("after_entry_id", *afterEntryID, goa.FormatUUID)) + } + { + limitRaw := qp.Get("limit") + if limitRaw != "" { + v, err2 := strconv.ParseInt(limitRaw, 10, strconv.IntSize) + if err2 != nil { + err = goa.MergeErrors(err, goa.InvalidFieldTypeError("limit", limitRaw, "integer")) + } + pv := int(v) + limit = &pv + } + } + if err != nil { + return nil, err + } + payload := NewGetHostTaskLogPayload(hostID, taskID, afterEntryID, limit) + + return payload, nil + } +} + +// EncodeGetHostTaskLogError returns an encoder for errors returned by the +// get-host-task-log control-plane endpoint. +func EncodeGetHostTaskLogError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error { + encodeError := goahttp.ErrorEncoder(encoder, formatter) + return func(ctx context.Context, w http.ResponseWriter, v error) error { + var en goa.GoaErrorNamer + if !errors.As(v, &en) { + return encodeError(ctx, w, v) + } + switch en.GoaErrorName() { + case "cluster_not_initialized": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetHostTaskLogClusterNotInitializedResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusConflict) + return enc.Encode(body) + case "invalid_input": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetHostTaskLogInvalidInputResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusBadRequest) + return enc.Encode(body) + case "not_found": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetHostTaskLogNotFoundResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusNotFound) + return enc.Encode(body) + case "server_error": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetHostTaskLogServerErrorResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusInternalServerError) + return enc.Encode(body) + default: + return encodeError(ctx, w, v) + } + } +} + +// EncodeListTasksResponse returns an encoder for responses returned by the +// control-plane list-tasks endpoint. +func EncodeListTasksResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { + return func(ctx context.Context, w http.ResponseWriter, v any) error { + res, _ := v.(*controlplane.ListTasksResponse) + enc := encoder(ctx, w) + body := NewListTasksResponseBody(res) + w.WriteHeader(http.StatusOK) + return enc.Encode(body) + } +} + +// DecodeListTasksRequest returns a decoder for requests sent to the +// control-plane list-tasks endpoint. +func DecodeListTasksRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (*controlplane.ListTasksPayload, error) { + return func(r *http.Request) (*controlplane.ListTasksPayload, error) { + var ( + scope *string + entityID *string + afterTaskID *string + limit *int + sortOrder *string + err error + ) + qp := r.URL.Query() + scopeRaw := qp.Get("scope") + if scopeRaw != "" { + scope = &scopeRaw + } + if scope != nil { + if !(*scope == "database" || *scope == "host") { + err = goa.MergeErrors(err, goa.InvalidEnumValueError("scope", *scope, []any{"database", "host"})) + } + } + entityIDRaw := qp.Get("entity_id") + if entityIDRaw != "" { + entityID = &entityIDRaw + } + if entityID != nil { + if utf8.RuneCountInString(*entityID) < 1 { + err = goa.MergeErrors(err, goa.InvalidLengthError("entity_id", *entityID, utf8.RuneCountInString(*entityID), 1, true)) + } + } + if entityID != nil { + if utf8.RuneCountInString(*entityID) > 63 { + err = goa.MergeErrors(err, goa.InvalidLengthError("entity_id", *entityID, utf8.RuneCountInString(*entityID), 63, false)) + } + } + afterTaskIDRaw := qp.Get("after_task_id") + if afterTaskIDRaw != "" { + afterTaskID = &afterTaskIDRaw + } + if afterTaskID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("after_task_id", *afterTaskID, goa.FormatUUID)) + } + { + limitRaw := qp.Get("limit") + if limitRaw != "" { + v, err2 := strconv.ParseInt(limitRaw, 10, strconv.IntSize) + if err2 != nil { + err = goa.MergeErrors(err, goa.InvalidFieldTypeError("limit", limitRaw, "integer")) + } + pv := int(v) + limit = &pv + } + } + sortOrderRaw := qp.Get("sort_order") + if sortOrderRaw != "" { + sortOrder = &sortOrderRaw + } + if sortOrder != nil { + if !(*sortOrder == "asc" || *sortOrder == "ascend" || *sortOrder == "ascending" || *sortOrder == "desc" || *sortOrder == "descend" || *sortOrder == "descending") { + err = goa.MergeErrors(err, goa.InvalidEnumValueError("sort_order", *sortOrder, []any{"asc", "ascend", "ascending", "desc", "descend", "descending"})) + } + } + if err != nil { + return nil, err + } + payload := NewListTasksPayload(scope, entityID, afterTaskID, limit, sortOrder) + + return payload, nil + } +} + +// EncodeListTasksError returns an encoder for errors returned by the +// list-tasks control-plane endpoint. +func EncodeListTasksError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error { + encodeError := goahttp.ErrorEncoder(encoder, formatter) + return func(ctx context.Context, w http.ResponseWriter, v error) error { + var en goa.GoaErrorNamer + if !errors.As(v, &en) { + return encodeError(ctx, w, v) + } + switch en.GoaErrorName() { + case "cluster_not_initialized": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewListTasksClusterNotInitializedResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusConflict) + return enc.Encode(body) + case "invalid_input": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewListTasksInvalidInputResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusBadRequest) + return enc.Encode(body) + case "server_error": + var res *controlplane.APIError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewListTasksServerErrorResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusInternalServerError) + return enc.Encode(body) + default: + return encodeError(ctx, w, v) + } + } +} + // EncodeRestoreDatabaseResponse returns an encoder for responses returned by // the control-plane restore-database endpoint. func EncodeRestoreDatabaseResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { diff --git a/api/apiv1/gen/http/control_plane/server/paths.go b/api/apiv1/gen/http/control_plane/server/paths.go index fc1deaa3..524c024d 100644 --- a/api/apiv1/gen/http/control_plane/server/paths.go +++ b/api/apiv1/gen/http/control_plane/server/paths.go @@ -106,6 +106,26 @@ func GetDatabaseTaskLogControlPlanePath(databaseID string, taskID string) string return fmt.Sprintf("/v1/databases/%v/tasks/%v/log", databaseID, taskID) } +// ListHostTasksControlPlanePath returns the URL path to the control-plane service list-host-tasks HTTP endpoint. +func ListHostTasksControlPlanePath(hostID string) string { + return fmt.Sprintf("/v1/hosts/%v/tasks", hostID) +} + +// GetHostTaskControlPlanePath returns the URL path to the control-plane service get-host-task HTTP endpoint. +func GetHostTaskControlPlanePath(hostID string, taskID string) string { + return fmt.Sprintf("/v1/hosts/%v/tasks/%v", hostID, taskID) +} + +// GetHostTaskLogControlPlanePath returns the URL path to the control-plane service get-host-task-log HTTP endpoint. +func GetHostTaskLogControlPlanePath(hostID string, taskID string) string { + return fmt.Sprintf("/v1/hosts/%v/tasks/%v/logs", hostID, taskID) +} + +// ListTasksControlPlanePath returns the URL path to the control-plane service list-tasks HTTP endpoint. +func ListTasksControlPlanePath() string { + return "/v1/tasks" +} + // RestoreDatabaseControlPlanePath returns the URL path to the control-plane service restore-database HTTP endpoint. func RestoreDatabaseControlPlanePath(databaseID string) string { return fmt.Sprintf("/v1/databases/%v/restore", databaseID) diff --git a/api/apiv1/gen/http/control_plane/server/server.go b/api/apiv1/gen/http/control_plane/server/server.go index 647ca796..2cd7669b 100644 --- a/api/apiv1/gen/http/control_plane/server/server.go +++ b/api/apiv1/gen/http/control_plane/server/server.go @@ -39,6 +39,10 @@ type Server struct { ListDatabaseTasks http.Handler GetDatabaseTask http.Handler GetDatabaseTaskLog http.Handler + ListHostTasks http.Handler + GetHostTask http.Handler + GetHostTaskLog http.Handler + ListTasks http.Handler RestoreDatabase http.Handler GetVersion http.Handler RestartInstance http.Handler @@ -99,6 +103,10 @@ func New( {"ListDatabaseTasks", "GET", "/v1/databases/{database_id}/tasks"}, {"GetDatabaseTask", "GET", "/v1/databases/{database_id}/tasks/{task_id}"}, {"GetDatabaseTaskLog", "GET", "/v1/databases/{database_id}/tasks/{task_id}/log"}, + {"ListHostTasks", "GET", "/v1/hosts/{host_id}/tasks"}, + {"GetHostTask", "GET", "/v1/hosts/{host_id}/tasks/{task_id}"}, + {"GetHostTaskLog", "GET", "/v1/hosts/{host_id}/tasks/{task_id}/logs"}, + {"ListTasks", "GET", "/v1/tasks"}, {"RestoreDatabase", "POST", "/v1/databases/{database_id}/restore"}, {"GetVersion", "GET", "/v1/version"}, {"RestartInstance", "POST", "/v1/databases/{database_id}/instances/{instance_id}/restart"}, @@ -126,6 +134,10 @@ func New( ListDatabaseTasks: NewListDatabaseTasksHandler(e.ListDatabaseTasks, mux, decoder, encoder, errhandler, formatter), GetDatabaseTask: NewGetDatabaseTaskHandler(e.GetDatabaseTask, mux, decoder, encoder, errhandler, formatter), GetDatabaseTaskLog: NewGetDatabaseTaskLogHandler(e.GetDatabaseTaskLog, mux, decoder, encoder, errhandler, formatter), + ListHostTasks: NewListHostTasksHandler(e.ListHostTasks, mux, decoder, encoder, errhandler, formatter), + GetHostTask: NewGetHostTaskHandler(e.GetHostTask, mux, decoder, encoder, errhandler, formatter), + GetHostTaskLog: NewGetHostTaskLogHandler(e.GetHostTaskLog, mux, decoder, encoder, errhandler, formatter), + ListTasks: NewListTasksHandler(e.ListTasks, mux, decoder, encoder, errhandler, formatter), RestoreDatabase: NewRestoreDatabaseHandler(e.RestoreDatabase, mux, decoder, encoder, errhandler, formatter), GetVersion: NewGetVersionHandler(e.GetVersion, mux, decoder, encoder, errhandler, formatter), RestartInstance: NewRestartInstanceHandler(e.RestartInstance, mux, decoder, encoder, errhandler, formatter), @@ -160,6 +172,10 @@ func (s *Server) Use(m func(http.Handler) http.Handler) { s.ListDatabaseTasks = m(s.ListDatabaseTasks) s.GetDatabaseTask = m(s.GetDatabaseTask) s.GetDatabaseTaskLog = m(s.GetDatabaseTaskLog) + s.ListHostTasks = m(s.ListHostTasks) + s.GetHostTask = m(s.GetHostTask) + s.GetHostTaskLog = m(s.GetHostTaskLog) + s.ListTasks = m(s.ListTasks) s.RestoreDatabase = m(s.RestoreDatabase) s.GetVersion = m(s.GetVersion) s.RestartInstance = m(s.RestartInstance) @@ -192,6 +208,10 @@ func Mount(mux goahttp.Muxer, h *Server) { MountListDatabaseTasksHandler(mux, h.ListDatabaseTasks) MountGetDatabaseTaskHandler(mux, h.GetDatabaseTask) MountGetDatabaseTaskLogHandler(mux, h.GetDatabaseTaskLog) + MountListHostTasksHandler(mux, h.ListHostTasks) + MountGetHostTaskHandler(mux, h.GetHostTask) + MountGetHostTaskLogHandler(mux, h.GetHostTaskLog) + MountListTasksHandler(mux, h.ListTasks) MountRestoreDatabaseHandler(mux, h.RestoreDatabase) MountGetVersionHandler(mux, h.GetVersion) MountRestartInstanceHandler(mux, h.RestartInstance) @@ -1189,6 +1209,218 @@ func NewGetDatabaseTaskLogHandler( }) } +// MountListHostTasksHandler configures the mux to serve the "control-plane" +// service "list-host-tasks" endpoint. +func MountListHostTasksHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("GET", "/v1/hosts/{host_id}/tasks", f) +} + +// NewListHostTasksHandler creates a HTTP handler which loads the HTTP request +// and calls the "control-plane" service "list-host-tasks" endpoint. +func NewListHostTasksHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeListHostTasksRequest(mux, decoder) + encodeResponse = EncodeListHostTasksResponse(encoder) + encodeError = EncodeListHostTasksError(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "list-host-tasks") + ctx = context.WithValue(ctx, goa.ServiceKey, "control-plane") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil && errhandler != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil && errhandler != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + if errhandler != nil { + errhandler(ctx, w, err) + } + } + }) +} + +// MountGetHostTaskHandler configures the mux to serve the "control-plane" +// service "get-host-task" endpoint. +func MountGetHostTaskHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("GET", "/v1/hosts/{host_id}/tasks/{task_id}", f) +} + +// NewGetHostTaskHandler creates a HTTP handler which loads the HTTP request +// and calls the "control-plane" service "get-host-task" endpoint. +func NewGetHostTaskHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeGetHostTaskRequest(mux, decoder) + encodeResponse = EncodeGetHostTaskResponse(encoder) + encodeError = EncodeGetHostTaskError(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "get-host-task") + ctx = context.WithValue(ctx, goa.ServiceKey, "control-plane") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil && errhandler != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil && errhandler != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + if errhandler != nil { + errhandler(ctx, w, err) + } + } + }) +} + +// MountGetHostTaskLogHandler configures the mux to serve the "control-plane" +// service "get-host-task-log" endpoint. +func MountGetHostTaskLogHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("GET", "/v1/hosts/{host_id}/tasks/{task_id}/logs", f) +} + +// NewGetHostTaskLogHandler creates a HTTP handler which loads the HTTP request +// and calls the "control-plane" service "get-host-task-log" endpoint. +func NewGetHostTaskLogHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeGetHostTaskLogRequest(mux, decoder) + encodeResponse = EncodeGetHostTaskLogResponse(encoder) + encodeError = EncodeGetHostTaskLogError(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "get-host-task-log") + ctx = context.WithValue(ctx, goa.ServiceKey, "control-plane") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil && errhandler != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil && errhandler != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + if errhandler != nil { + errhandler(ctx, w, err) + } + } + }) +} + +// MountListTasksHandler configures the mux to serve the "control-plane" +// service "list-tasks" endpoint. +func MountListTasksHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("GET", "/v1/tasks", f) +} + +// NewListTasksHandler creates a HTTP handler which loads the HTTP request and +// calls the "control-plane" service "list-tasks" endpoint. +func NewListTasksHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeListTasksRequest(mux, decoder) + encodeResponse = EncodeListTasksResponse(encoder) + encodeError = EncodeListTasksError(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "list-tasks") + ctx = context.WithValue(ctx, goa.ServiceKey, "control-plane") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil && errhandler != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil && errhandler != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + if errhandler != nil { + errhandler(ctx, w, err) + } + } + }) +} + // MountRestoreDatabaseHandler configures the mux to serve the "control-plane" // service "restore-database" endpoint. func MountRestoreDatabaseHandler(mux goahttp.Muxer, h http.Handler) { diff --git a/api/apiv1/gen/http/control_plane/server/types.go b/api/apiv1/gen/http/control_plane/server/types.go index 6050ea93..18ffa2fe 100644 --- a/api/apiv1/gen/http/control_plane/server/types.go +++ b/api/apiv1/gen/http/control_plane/server/types.go @@ -306,6 +306,68 @@ type GetDatabaseTaskLogResponseBody struct { Entries []*TaskLogEntryResponseBody `form:"entries" json:"entries" xml:"entries"` } +// ListHostTasksResponseBody is the type of the "control-plane" service +// "list-host-tasks" endpoint HTTP response body. +type ListHostTasksResponseBody struct { + Tasks []*TaskResponseBody `form:"tasks,omitempty" json:"tasks,omitempty" xml:"tasks,omitempty"` +} + +// GetHostTaskResponseBody is the type of the "control-plane" service +// "get-host-task" endpoint HTTP response body. +type GetHostTaskResponseBody struct { + // The parent task ID of the task. + ParentID *string `form:"parent_id,omitempty" json:"parent_id,omitempty" xml:"parent_id,omitempty"` + // The scope of the task (database or host). + Scope string `form:"scope" json:"scope" xml:"scope"` + // The entity ID (database_id or host_id) that this task belongs to. + EntityID string `form:"entity_id" json:"entity_id" xml:"entity_id"` + // The database ID of the task. + DatabaseID *string `form:"database_id,omitempty" json:"database_id,omitempty" xml:"database_id,omitempty"` + // The name of the node that the task is operating on. + NodeName *string `form:"node_name,omitempty" json:"node_name,omitempty" xml:"node_name,omitempty"` + // The ID of the instance that the task is operating on. + InstanceID *string `form:"instance_id,omitempty" json:"instance_id,omitempty" xml:"instance_id,omitempty"` + // The ID of the host that the task is running on. + HostID *string `form:"host_id,omitempty" json:"host_id,omitempty" xml:"host_id,omitempty"` + // The unique ID of the task. + TaskID string `form:"task_id" json:"task_id" xml:"task_id"` + // The time when the task was created. + CreatedAt string `form:"created_at" json:"created_at" xml:"created_at"` + // The time when the task was completed. + CompletedAt *string `form:"completed_at,omitempty" json:"completed_at,omitempty" xml:"completed_at,omitempty"` + // The type of the task. + Type string `form:"type" json:"type" xml:"type"` + // The status of the task. + Status string `form:"status" json:"status" xml:"status"` + // The error message if the task failed. + Error *string `form:"error,omitempty" json:"error,omitempty" xml:"error,omitempty"` +} + +// GetHostTaskLogResponseBody is the type of the "control-plane" service +// "get-host-task-log" endpoint HTTP response body. +type GetHostTaskLogResponseBody struct { + // The scope of the task (database or host). + Scope string `form:"scope" json:"scope" xml:"scope"` + // The entity ID (database_id or host_id) that this task log belongs to. + EntityID string `form:"entity_id" json:"entity_id" xml:"entity_id"` + // The database ID of the task log. Deprecated: use entity_id instead. + DatabaseID *string `form:"database_id,omitempty" json:"database_id,omitempty" xml:"database_id,omitempty"` + // The unique ID of the task log. + TaskID string `form:"task_id" json:"task_id" xml:"task_id"` + // The status of the task. + TaskStatus string `form:"task_status" json:"task_status" xml:"task_status"` + // The ID of the last entry in the task log. + LastEntryID *string `form:"last_entry_id,omitempty" json:"last_entry_id,omitempty" xml:"last_entry_id,omitempty"` + // Entries in the task log. + Entries []*TaskLogEntryResponseBody `form:"entries" json:"entries" xml:"entries"` +} + +// ListTasksResponseBody is the type of the "control-plane" service +// "list-tasks" endpoint HTTP response body. +type ListTasksResponseBody struct { + Tasks []*TaskResponseBody `form:"tasks,omitempty" json:"tasks,omitempty" xml:"tasks,omitempty"` +} + // RestoreDatabaseResponseBody is the type of the "control-plane" service // "restore-database" endpoint HTTP response body. type RestoreDatabaseResponseBody struct { @@ -1154,6 +1216,152 @@ type GetDatabaseTaskLogServerErrorResponseBody struct { Message string `form:"message" json:"message" xml:"message"` } +// ListHostTasksClusterNotInitializedResponseBody is the type of the +// "control-plane" service "list-host-tasks" endpoint HTTP response body for +// the "cluster_not_initialized" error. +type ListHostTasksClusterNotInitializedResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// ListHostTasksInvalidInputResponseBody is the type of the "control-plane" +// service "list-host-tasks" endpoint HTTP response body for the +// "invalid_input" error. +type ListHostTasksInvalidInputResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// ListHostTasksNotFoundResponseBody is the type of the "control-plane" service +// "list-host-tasks" endpoint HTTP response body for the "not_found" error. +type ListHostTasksNotFoundResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// ListHostTasksServerErrorResponseBody is the type of the "control-plane" +// service "list-host-tasks" endpoint HTTP response body for the "server_error" +// error. +type ListHostTasksServerErrorResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// GetHostTaskClusterNotInitializedResponseBody is the type of the +// "control-plane" service "get-host-task" endpoint HTTP response body for the +// "cluster_not_initialized" error. +type GetHostTaskClusterNotInitializedResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// GetHostTaskInvalidInputResponseBody is the type of the "control-plane" +// service "get-host-task" endpoint HTTP response body for the "invalid_input" +// error. +type GetHostTaskInvalidInputResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// GetHostTaskNotFoundResponseBody is the type of the "control-plane" service +// "get-host-task" endpoint HTTP response body for the "not_found" error. +type GetHostTaskNotFoundResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// GetHostTaskServerErrorResponseBody is the type of the "control-plane" +// service "get-host-task" endpoint HTTP response body for the "server_error" +// error. +type GetHostTaskServerErrorResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// GetHostTaskLogClusterNotInitializedResponseBody is the type of the +// "control-plane" service "get-host-task-log" endpoint HTTP response body for +// the "cluster_not_initialized" error. +type GetHostTaskLogClusterNotInitializedResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// GetHostTaskLogInvalidInputResponseBody is the type of the "control-plane" +// service "get-host-task-log" endpoint HTTP response body for the +// "invalid_input" error. +type GetHostTaskLogInvalidInputResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// GetHostTaskLogNotFoundResponseBody is the type of the "control-plane" +// service "get-host-task-log" endpoint HTTP response body for the "not_found" +// error. +type GetHostTaskLogNotFoundResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// GetHostTaskLogServerErrorResponseBody is the type of the "control-plane" +// service "get-host-task-log" endpoint HTTP response body for the +// "server_error" error. +type GetHostTaskLogServerErrorResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// ListTasksClusterNotInitializedResponseBody is the type of the +// "control-plane" service "list-tasks" endpoint HTTP response body for the +// "cluster_not_initialized" error. +type ListTasksClusterNotInitializedResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// ListTasksInvalidInputResponseBody is the type of the "control-plane" service +// "list-tasks" endpoint HTTP response body for the "invalid_input" error. +type ListTasksInvalidInputResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + +// ListTasksServerErrorResponseBody is the type of the "control-plane" service +// "list-tasks" endpoint HTTP response body for the "server_error" error. +type ListTasksServerErrorResponseBody struct { + // The name of the error. + Name string `form:"name" json:"name" xml:"name"` + // The error message. + Message string `form:"message" json:"message" xml:"message"` +} + // RestoreDatabaseClusterNotInitializedResponseBody is the type of the // "control-plane" service "restore-database" endpoint HTTP response body for // the "cluster_not_initialized" error. @@ -2759,6 +2967,87 @@ func NewGetDatabaseTaskLogResponseBody(res *controlplane.TaskLog) *GetDatabaseTa return body } +// NewListHostTasksResponseBody builds the HTTP response body from the result +// of the "list-host-tasks" endpoint of the "control-plane" service. +func NewListHostTasksResponseBody(res *controlplane.ListHostTasksResponse) *ListHostTasksResponseBody { + body := &ListHostTasksResponseBody{} + if res.Tasks != nil { + body.Tasks = make([]*TaskResponseBody, len(res.Tasks)) + for i, val := range res.Tasks { + if val == nil { + body.Tasks[i] = nil + continue + } + body.Tasks[i] = marshalControlplaneTaskToTaskResponseBody(val) + } + } + return body +} + +// NewGetHostTaskResponseBody builds the HTTP response body from the result of +// the "get-host-task" endpoint of the "control-plane" service. +func NewGetHostTaskResponseBody(res *controlplane.Task) *GetHostTaskResponseBody { + body := &GetHostTaskResponseBody{ + ParentID: res.ParentID, + Scope: res.Scope, + EntityID: res.EntityID, + DatabaseID: res.DatabaseID, + NodeName: res.NodeName, + InstanceID: res.InstanceID, + HostID: res.HostID, + TaskID: res.TaskID, + CreatedAt: res.CreatedAt, + CompletedAt: res.CompletedAt, + Type: res.Type, + Status: res.Status, + Error: res.Error, + } + return body +} + +// NewGetHostTaskLogResponseBody builds the HTTP response body from the result +// of the "get-host-task-log" endpoint of the "control-plane" service. +func NewGetHostTaskLogResponseBody(res *controlplane.TaskLog) *GetHostTaskLogResponseBody { + body := &GetHostTaskLogResponseBody{ + Scope: res.Scope, + EntityID: res.EntityID, + DatabaseID: res.DatabaseID, + TaskID: res.TaskID, + TaskStatus: res.TaskStatus, + LastEntryID: res.LastEntryID, + } + if res.Entries != nil { + body.Entries = make([]*TaskLogEntryResponseBody, len(res.Entries)) + for i, val := range res.Entries { + if val == nil { + body.Entries[i] = nil + continue + } + body.Entries[i] = marshalControlplaneTaskLogEntryToTaskLogEntryResponseBody(val) + } + } else { + body.Entries = []*TaskLogEntryResponseBody{} + } + return body +} + +// NewListTasksResponseBody builds the HTTP response body from the result of +// the "list-tasks" endpoint of the "control-plane" service. +func NewListTasksResponseBody(res *controlplane.ListTasksResponse) *ListTasksResponseBody { + body := &ListTasksResponseBody{} + if res.Tasks != nil { + body.Tasks = make([]*TaskResponseBody, len(res.Tasks)) + for i, val := range res.Tasks { + if val == nil { + body.Tasks[i] = nil + continue + } + body.Tasks[i] = marshalControlplaneTaskToTaskResponseBody(val) + } + } + return body +} + // NewRestoreDatabaseResponseBody builds the HTTP response body from the result // of the "restore-database" endpoint of the "control-plane" service. func NewRestoreDatabaseResponseBody(res *controlplane.RestoreDatabaseResponse) *RestoreDatabaseResponseBody { @@ -3675,6 +3964,161 @@ func NewGetDatabaseTaskLogServerErrorResponseBody(res *controlplane.APIError) *G return body } +// NewListHostTasksClusterNotInitializedResponseBody builds the HTTP response +// body from the result of the "list-host-tasks" endpoint of the +// "control-plane" service. +func NewListHostTasksClusterNotInitializedResponseBody(res *controlplane.APIError) *ListHostTasksClusterNotInitializedResponseBody { + body := &ListHostTasksClusterNotInitializedResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewListHostTasksInvalidInputResponseBody builds the HTTP response body from +// the result of the "list-host-tasks" endpoint of the "control-plane" service. +func NewListHostTasksInvalidInputResponseBody(res *controlplane.APIError) *ListHostTasksInvalidInputResponseBody { + body := &ListHostTasksInvalidInputResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewListHostTasksNotFoundResponseBody builds the HTTP response body from the +// result of the "list-host-tasks" endpoint of the "control-plane" service. +func NewListHostTasksNotFoundResponseBody(res *controlplane.APIError) *ListHostTasksNotFoundResponseBody { + body := &ListHostTasksNotFoundResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewListHostTasksServerErrorResponseBody builds the HTTP response body from +// the result of the "list-host-tasks" endpoint of the "control-plane" service. +func NewListHostTasksServerErrorResponseBody(res *controlplane.APIError) *ListHostTasksServerErrorResponseBody { + body := &ListHostTasksServerErrorResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewGetHostTaskClusterNotInitializedResponseBody builds the HTTP response +// body from the result of the "get-host-task" endpoint of the "control-plane" +// service. +func NewGetHostTaskClusterNotInitializedResponseBody(res *controlplane.APIError) *GetHostTaskClusterNotInitializedResponseBody { + body := &GetHostTaskClusterNotInitializedResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewGetHostTaskInvalidInputResponseBody builds the HTTP response body from +// the result of the "get-host-task" endpoint of the "control-plane" service. +func NewGetHostTaskInvalidInputResponseBody(res *controlplane.APIError) *GetHostTaskInvalidInputResponseBody { + body := &GetHostTaskInvalidInputResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewGetHostTaskNotFoundResponseBody builds the HTTP response body from the +// result of the "get-host-task" endpoint of the "control-plane" service. +func NewGetHostTaskNotFoundResponseBody(res *controlplane.APIError) *GetHostTaskNotFoundResponseBody { + body := &GetHostTaskNotFoundResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewGetHostTaskServerErrorResponseBody builds the HTTP response body from the +// result of the "get-host-task" endpoint of the "control-plane" service. +func NewGetHostTaskServerErrorResponseBody(res *controlplane.APIError) *GetHostTaskServerErrorResponseBody { + body := &GetHostTaskServerErrorResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewGetHostTaskLogClusterNotInitializedResponseBody builds the HTTP response +// body from the result of the "get-host-task-log" endpoint of the +// "control-plane" service. +func NewGetHostTaskLogClusterNotInitializedResponseBody(res *controlplane.APIError) *GetHostTaskLogClusterNotInitializedResponseBody { + body := &GetHostTaskLogClusterNotInitializedResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewGetHostTaskLogInvalidInputResponseBody builds the HTTP response body from +// the result of the "get-host-task-log" endpoint of the "control-plane" +// service. +func NewGetHostTaskLogInvalidInputResponseBody(res *controlplane.APIError) *GetHostTaskLogInvalidInputResponseBody { + body := &GetHostTaskLogInvalidInputResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewGetHostTaskLogNotFoundResponseBody builds the HTTP response body from the +// result of the "get-host-task-log" endpoint of the "control-plane" service. +func NewGetHostTaskLogNotFoundResponseBody(res *controlplane.APIError) *GetHostTaskLogNotFoundResponseBody { + body := &GetHostTaskLogNotFoundResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewGetHostTaskLogServerErrorResponseBody builds the HTTP response body from +// the result of the "get-host-task-log" endpoint of the "control-plane" +// service. +func NewGetHostTaskLogServerErrorResponseBody(res *controlplane.APIError) *GetHostTaskLogServerErrorResponseBody { + body := &GetHostTaskLogServerErrorResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewListTasksClusterNotInitializedResponseBody builds the HTTP response body +// from the result of the "list-tasks" endpoint of the "control-plane" service. +func NewListTasksClusterNotInitializedResponseBody(res *controlplane.APIError) *ListTasksClusterNotInitializedResponseBody { + body := &ListTasksClusterNotInitializedResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewListTasksInvalidInputResponseBody builds the HTTP response body from the +// result of the "list-tasks" endpoint of the "control-plane" service. +func NewListTasksInvalidInputResponseBody(res *controlplane.APIError) *ListTasksInvalidInputResponseBody { + body := &ListTasksInvalidInputResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + +// NewListTasksServerErrorResponseBody builds the HTTP response body from the +// result of the "list-tasks" endpoint of the "control-plane" service. +func NewListTasksServerErrorResponseBody(res *controlplane.APIError) *ListTasksServerErrorResponseBody { + body := &ListTasksServerErrorResponseBody{ + Name: res.Name, + Message: res.Message, + } + return body +} + // NewRestoreDatabaseClusterNotInitializedResponseBody builds the HTTP response // body from the result of the "restore-database" endpoint of the // "control-plane" service. @@ -4112,6 +4556,56 @@ func NewGetDatabaseTaskLogPayload(databaseID string, taskID string, afterEntryID return v } +// NewListHostTasksPayload builds a control-plane service list-host-tasks +// endpoint payload. +func NewListHostTasksPayload(hostID string, afterTaskID *string, limit *int, sortOrder *string) *controlplane.ListHostTasksPayload { + v := &controlplane.ListHostTasksPayload{} + v.HostID = controlplane.Identifier(hostID) + v.AfterTaskID = afterTaskID + v.Limit = limit + v.SortOrder = sortOrder + + return v +} + +// NewGetHostTaskPayload builds a control-plane service get-host-task endpoint +// payload. +func NewGetHostTaskPayload(hostID string, taskID string) *controlplane.GetHostTaskPayload { + v := &controlplane.GetHostTaskPayload{} + v.HostID = controlplane.Identifier(hostID) + v.TaskID = taskID + + return v +} + +// NewGetHostTaskLogPayload builds a control-plane service get-host-task-log +// endpoint payload. +func NewGetHostTaskLogPayload(hostID string, taskID string, afterEntryID *string, limit *int) *controlplane.GetHostTaskLogPayload { + v := &controlplane.GetHostTaskLogPayload{} + v.HostID = controlplane.Identifier(hostID) + v.TaskID = taskID + v.AfterEntryID = afterEntryID + v.Limit = limit + + return v +} + +// NewListTasksPayload builds a control-plane service list-tasks endpoint +// payload. +func NewListTasksPayload(scope *string, entityID *string, afterTaskID *string, limit *int, sortOrder *string) *controlplane.ListTasksPayload { + v := &controlplane.ListTasksPayload{} + v.Scope = scope + if entityID != nil { + tmpentityID := controlplane.Identifier(*entityID) + v.EntityID = &tmpentityID + } + v.AfterTaskID = afterTaskID + v.Limit = limit + v.SortOrder = sortOrder + + return v +} + // NewRestoreDatabasePayload builds a control-plane service restore-database // endpoint payload. func NewRestoreDatabasePayload(body *RestoreDatabaseRequestBody, databaseID string, force bool) *controlplane.RestoreDatabasePayload { diff --git a/api/apiv1/gen/http/openapi.json b/api/apiv1/gen/http/openapi.json index dcc0c18b..3a341660 100644 --- a/api/apiv1/gen/http/openapi.json +++ b/api/apiv1/gen/http/openapi.json @@ -1788,6 +1788,393 @@ ] } }, + "/v1/hosts/{host_id}/tasks": { + "get": { + "tags": [ + "Host" + ], + "summary": "List host tasks", + "description": "Lists all tasks for a host.", + "operationId": "control-plane#list-host-tasks", + "parameters": [ + { + "name": "after_task_id", + "in": "query", + "description": "ID of the task to start from.", + "required": false, + "type": "string", + "format": "uuid" + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of tasks to return.", + "required": false, + "type": "integer" + }, + { + "name": "sort_order", + "in": "query", + "description": "Sort order for the tasks.", + "required": false, + "type": "string", + "enum": [ + "asc", + "ascend", + "ascending", + "desc", + "descend", + "descending" + ] + }, + { + "name": "host_id", + "in": "path", + "description": "A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens.", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK response.", + "schema": { + "$ref": "#/definitions/ListHostTasksResponse" + } + }, + "400": { + "description": "Bad Request response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "404": { + "description": "Not Found response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "409": { + "description": "Conflict response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "500": { + "description": "Internal Server Error response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + } + }, + "schemes": [ + "http" + ] + } + }, + "/v1/hosts/{host_id}/tasks/{task_id}": { + "get": { + "tags": [ + "Host" + ], + "summary": "Get host task", + "description": "Returns information about a particular task for a host.", + "operationId": "control-plane#get-host-task", + "parameters": [ + { + "name": "host_id", + "in": "path", + "description": "A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens.", + "required": true, + "type": "string" + }, + { + "name": "task_id", + "in": "path", + "description": "ID of the task to get.", + "required": true, + "type": "string", + "format": "uuid" + } + ], + "responses": { + "200": { + "description": "OK response.", + "schema": { + "$ref": "#/definitions/Task", + "required": [ + "scope", + "entity_id", + "task_id", + "created_at", + "type", + "status" + ] + } + }, + "400": { + "description": "Bad Request response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "404": { + "description": "Not Found response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "409": { + "description": "Conflict response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "500": { + "description": "Internal Server Error response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + } + }, + "schemes": [ + "http" + ] + } + }, + "/v1/hosts/{host_id}/tasks/{task_id}/logs": { + "get": { + "tags": [ + "Host" + ], + "summary": "Get host task logs", + "description": "Returns the log of a particular task for a host.", + "operationId": "control-plane#get-host-task-log", + "parameters": [ + { + "name": "after_entry_id", + "in": "query", + "description": "ID of the entry to start from.", + "required": false, + "type": "string", + "format": "uuid" + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of entries to return.", + "required": false, + "type": "integer" + }, + { + "name": "host_id", + "in": "path", + "description": "A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens.", + "required": true, + "type": "string" + }, + { + "name": "task_id", + "in": "path", + "description": "ID of the task to get the logs for.", + "required": true, + "type": "string", + "format": "uuid" + } + ], + "responses": { + "200": { + "description": "OK response.", + "schema": { + "$ref": "#/definitions/TaskLog", + "required": [ + "scope", + "entity_id", + "task_id", + "task_status", + "entries" + ] + } + }, + "400": { + "description": "Bad Request response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "404": { + "description": "Not Found response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "409": { + "description": "Conflict response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "500": { + "description": "Internal Server Error response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + } + }, + "schemes": [ + "http" + ] + } + }, + "/v1/tasks": { + "get": { + "tags": [ + "System" + ], + "summary": "List tasks", + "description": "Lists tasks across all scopes with optional filtering by scope and entity ID.", + "operationId": "control-plane#list-tasks", + "parameters": [ + { + "name": "scope", + "in": "query", + "description": "Optional scope to filter tasks (database or host).", + "required": false, + "type": "string", + "enum": [ + "database", + "host" + ] + }, + { + "name": "entity_id", + "in": "query", + "description": "A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens.", + "required": false, + "type": "string" + }, + { + "name": "after_task_id", + "in": "query", + "description": "ID of the task to start from.", + "required": false, + "type": "string", + "format": "uuid" + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of tasks to return.", + "required": false, + "type": "integer" + }, + { + "name": "sort_order", + "in": "query", + "description": "Sort order for the tasks.", + "required": false, + "type": "string", + "enum": [ + "asc", + "ascend", + "ascending", + "desc", + "descend", + "descending" + ] + } + ], + "responses": { + "200": { + "description": "OK response.", + "schema": { + "$ref": "#/definitions/ListTasksResponse" + } + }, + "400": { + "description": "Bad Request response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "409": { + "description": "Conflict response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + }, + "500": { + "description": "Internal Server Error response.", + "schema": { + "$ref": "#/definitions/APIError", + "required": [ + "name", + "message" + ] + } + } + }, + "schemes": [ + "http" + ] + } + }, "/v1/version": { "get": { "tags": [ @@ -6048,6 +6435,54 @@ ] } }, + "ListHostTasksResponse": { + "title": "ListHostTasksResponse", + "type": "object", + "properties": { + "tasks": { + "type": "array", + "items": { + "$ref": "#/definitions/Task" + }, + "example": [ + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + } + ] + } + }, + "example": { + "tasks": [ + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "entity_id": "host-1", + "host_id": "host-1", + "scope": "host", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "remove_host" + } + ] + } + }, "ListHostsResponse": { "title": "ListHostsResponse", "type": "object", @@ -6304,6 +6739,85 @@ "hosts" ] }, + "ListTasksResponse": { + "title": "ListTasksResponse", + "type": "object", + "properties": { + "tasks": { + "type": "array", + "items": { + "$ref": "#/definitions/Task" + }, + "example": [ + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + } + ] + } + }, + "example": { + "tasks": [ + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "database_id": "storefront", + "entity_id": "storefront", + "instance_id": "storefront-n1-689qacsi", + "scope": "database", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "node_backup" + }, + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "entity_id": "host-1", + "host_id": "host-1", + "scope": "host", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "remove_host" + } + ] + } + }, "Listdatabasesresponse": { "title": "Mediatype identifier: listdatabasesresponse; view=default", "type": "object", @@ -6643,7 +7157,7 @@ "type": "array", "items": { "type": "string", - "example": "Aut dignissimos cum voluptate modi consequatur." + "example": "Cum voluptate modi consequatur non at esse." }, "description": "The nodes to restore. Defaults to all nodes if empty or unspecified.", "example": [ diff --git a/api/apiv1/gen/http/openapi.yaml b/api/apiv1/gen/http/openapi.yaml index 8fadbd5d..e6df67f0 100644 --- a/api/apiv1/gen/http/openapi.yaml +++ b/api/apiv1/gen/http/openapi.yaml @@ -1242,6 +1242,281 @@ paths: - message schemes: - http + /v1/hosts/{host_id}/tasks: + get: + tags: + - Host + summary: List host tasks + description: Lists all tasks for a host. + operationId: control-plane#list-host-tasks + parameters: + - name: after_task_id + in: query + description: ID of the task to start from. + required: false + type: string + format: uuid + - name: limit + in: query + description: Maximum number of tasks to return. + required: false + type: integer + - name: sort_order + in: query + description: Sort order for the tasks. + required: false + type: string + enum: + - asc + - ascend + - ascending + - desc + - descend + - descending + - name: host_id + in: path + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + required: true + type: string + responses: + "200": + description: OK response. + schema: + $ref: '#/definitions/ListHostTasksResponse' + "400": + description: Bad Request response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "404": + description: Not Found response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "409": + description: Conflict response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "500": + description: Internal Server Error response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + schemes: + - http + /v1/hosts/{host_id}/tasks/{task_id}: + get: + tags: + - Host + summary: Get host task + description: Returns information about a particular task for a host. + operationId: control-plane#get-host-task + parameters: + - name: host_id + in: path + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + required: true + type: string + - name: task_id + in: path + description: ID of the task to get. + required: true + type: string + format: uuid + responses: + "200": + description: OK response. + schema: + $ref: '#/definitions/Task' + required: + - scope + - entity_id + - task_id + - created_at + - type + - status + "400": + description: Bad Request response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "404": + description: Not Found response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "409": + description: Conflict response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "500": + description: Internal Server Error response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + schemes: + - http + /v1/hosts/{host_id}/tasks/{task_id}/logs: + get: + tags: + - Host + summary: Get host task logs + description: Returns the log of a particular task for a host. + operationId: control-plane#get-host-task-log + parameters: + - name: after_entry_id + in: query + description: ID of the entry to start from. + required: false + type: string + format: uuid + - name: limit + in: query + description: Maximum number of entries to return. + required: false + type: integer + - name: host_id + in: path + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + required: true + type: string + - name: task_id + in: path + description: ID of the task to get the logs for. + required: true + type: string + format: uuid + responses: + "200": + description: OK response. + schema: + $ref: '#/definitions/TaskLog' + required: + - scope + - entity_id + - task_id + - task_status + - entries + "400": + description: Bad Request response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "404": + description: Not Found response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "409": + description: Conflict response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "500": + description: Internal Server Error response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + schemes: + - http + /v1/tasks: + get: + tags: + - System + summary: List tasks + description: Lists tasks across all scopes with optional filtering by scope and entity ID. + operationId: control-plane#list-tasks + parameters: + - name: scope + in: query + description: Optional scope to filter tasks (database or host). + required: false + type: string + enum: + - database + - host + - name: entity_id + in: query + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + required: false + type: string + - name: after_task_id + in: query + description: ID of the task to start from. + required: false + type: string + format: uuid + - name: limit + in: query + description: Maximum number of tasks to return. + required: false + type: integer + - name: sort_order + in: query + description: Sort order for the tasks. + required: false + type: string + enum: + - asc + - ascend + - ascending + - desc + - descend + - descending + responses: + "200": + description: OK response. + schema: + $ref: '#/definitions/ListTasksResponse' + "400": + description: Bad Request response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "409": + description: Conflict response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + "500": + description: Internal Server Error response. + schema: + $ref: '#/definitions/APIError' + required: + - name + - message + schemes: + - http /v1/version: get: tags: @@ -4365,6 +4640,41 @@ definitions: status: completed task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 type: create + ListHostTasksResponse: + title: ListHostTasksResponse + type: object + properties: + tasks: + type: array + items: + $ref: '#/definitions/Task' + example: + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + example: + tasks: + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + entity_id: host-1 + host_id: host-1 + scope: host + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: remove_host ListHostsResponse: title: ListHostsResponse type: object @@ -4535,6 +4845,66 @@ definitions: spock_version: "5" required: - hosts + ListTasksResponse: + title: ListTasksResponse + type: object + properties: + tasks: + type: array + items: + $ref: '#/definitions/Task' + example: + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + example: + tasks: + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + database_id: storefront + entity_id: storefront + instance_id: storefront-n1-689qacsi + scope: database + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: node_backup + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + entity_id: host-1 + host_id: host-1 + scope: host + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: remove_host Listdatabasesresponse: title: 'Mediatype identifier: listdatabasesresponse; view=default' type: object @@ -4780,7 +5150,7 @@ definitions: type: array items: type: string - example: Aut dignissimos cum voluptate modi consequatur. + example: Cum voluptate modi consequatur non at esse. description: The nodes to restore. Defaults to all nodes if empty or unspecified. example: - n1 diff --git a/api/apiv1/gen/http/openapi3.json b/api/apiv1/gen/http/openapi3.json index b07d8591..58439ec8 100644 --- a/api/apiv1/gen/http/openapi3.json +++ b/api/apiv1/gen/http/openapi3.json @@ -4094,27 +4094,139 @@ } } }, - "/v1/version": { + "/v1/hosts/{host_id}/tasks": { "get": { "tags": [ - "System" + "Host" + ], + "summary": "List host tasks", + "description": "Lists all tasks for a host.", + "operationId": "list-host-tasks", + "parameters": [ + { + "name": "after_task_id", + "in": "query", + "description": "ID of the task to start from.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "ID of the task to start from.", + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348", + "format": "uuid" + }, + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348" + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of tasks to return.", + "allowEmptyValue": true, + "schema": { + "type": "integer", + "description": "Maximum number of tasks to return.", + "example": 100, + "format": "int64" + }, + "example": 100 + }, + { + "name": "sort_order", + "in": "query", + "description": "Sort order for the tasks.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Sort order for the tasks.", + "example": "ascend", + "enum": [ + "asc", + "ascend", + "ascending", + "desc", + "descend", + "descending" + ] + }, + "example": "ascend" + }, + { + "name": "host_id", + "in": "path", + "description": "ID of the host to list tasks for.", + "required": true, + "schema": { + "type": "string", + "description": "A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens.", + "example": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "minLength": 1, + "maxLength": 63 + }, + "example": "host-1" + } ], - "summary": "Get version", - "description": "Returns version information for this Control Plane server.", - "operationId": "get-version", "responses": { "200": { "description": "OK response.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VersionInfo" + "$ref": "#/components/schemas/ListHostTasksResponse" }, "example": { - "arch": "amd64", - "revision": "e89ae93b", - "revision_time": "2025-01-01T01:30:00Z", - "version": "1.0.0" + "tasks": [ + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "entity_id": "host-1", + "host_id": "host-1", + "scope": "host", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "remove_host" + } + ] + } + } + } + }, + "400": { + "description": "invalid_input: Bad Request response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "404": { + "description": "not_found: Not Found response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "409": { + "description": "cluster_not_initialized: Conflict response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" } } } @@ -4135,96 +4247,686 @@ } } } - } - }, - "components": { - "schemas": { - "APIError": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "The error message.", - "example": "A longer description of the error." + }, + "/v1/hosts/{host_id}/tasks/{task_id}": { + "get": { + "tags": [ + "Host" + ], + "summary": "Get host task", + "description": "Returns information about a particular task for a host.", + "operationId": "get-host-task", + "parameters": [ + { + "name": "host_id", + "in": "path", + "description": "ID of the host the task belongs to.", + "required": true, + "schema": { + "type": "string", + "description": "A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens.", + "example": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "minLength": 1, + "maxLength": 63 + }, + "example": "host-1" }, - "name": { - "type": "string", - "description": "The name of the error.", - "example": "error_name" - } - }, - "description": "A Control Plane API error.", - "example": { - "message": "A longer description of the error.", - "name": "error_name" - }, - "required": [ - "name", - "message" - ] - }, - "BackupConfigSpec": { - "type": "object", - "properties": { - "repositories": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BackupRepositorySpec" + { + "name": "task_id", + "in": "path", + "description": "ID of the task to get.", + "required": true, + "schema": { + "type": "string", + "description": "ID of the task to get.", + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348", + "format": "uuid" }, - "description": "The repositories for this backup configuration.", - "example": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348" + } + ], + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Task" }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" + "example": { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + } } - ], - "minItems": 1 + } }, - "schedules": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BackupScheduleSpec" - }, - "description": "The schedules for this backup configuration.", - "example": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ], - "maxItems": 32 - } - }, + "400": { + "description": "invalid_input: Bad Request response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "404": { + "description": "not_found: Not Found response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "409": { + "description": "cluster_not_initialized: Conflict response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "500": { + "description": "server_error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + } + } + } + }, + "/v1/hosts/{host_id}/tasks/{task_id}/logs": { + "get": { + "tags": [ + "Host" + ], + "summary": "Get host task logs", + "description": "Returns the log of a particular task for a host.", + "operationId": "get-host-task-log", + "parameters": [ + { + "name": "after_entry_id", + "in": "query", + "description": "ID of the entry to start from.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "ID of the entry to start from.", + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348", + "format": "uuid" + }, + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348" + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of entries to return.", + "allowEmptyValue": true, + "schema": { + "type": "integer", + "description": "Maximum number of entries to return.", + "example": 100, + "format": "int64" + }, + "example": 100 + }, + { + "name": "host_id", + "in": "path", + "description": "ID of the host to get the task logs for.", + "required": true, + "schema": { + "type": "string", + "description": "A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens.", + "example": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "minLength": 1, + "maxLength": 63 + }, + "example": "host-1" + }, + { + "name": "task_id", + "in": "path", + "description": "ID of the task to get the logs for.", + "required": true, + "schema": { + "type": "string", + "description": "ID of the task to get the logs for.", + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348", + "format": "uuid" + }, + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348" + } + ], + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskLog" + }, + "examples": { + "node_backup task log": { + "summary": "node_backup task log", + "description": "The task log from a 'node_backup' task. These messages are produced by pgbackrest.", + "value": { + "entity_id": "storefront", + "entries": [ + { + "message": "P00 INFO: backup command begin 2.55.1: --config=/opt/pgedge/configs/pgbackrest.backup.conf --exec-id=198-b17fae6e --log-level-console=info --no-log-timestamp --pg1-path=/opt/pgedge/data/pgdata --pg1-user=pgedge --repo1-cipher-type=none --repo1-path=/backups/databases/storefront/n1 --repo1-retention-full=7 --repo1-retention-full-type=time --repo1-type=posix --stanza=db --start-fast --type=full", + "timestamp": "2025-06-18T17:54:34Z" + }, + { + "message": "P00 INFO: execute non-exclusive backup start: backup begins after the requested immediate checkpoint completes", + "timestamp": "2025-06-18T17:54:34Z" + }, + { + "message": "P00 INFO: backup start archive = 000000020000000000000004, lsn = 0/4000028", + "timestamp": "2025-06-18T17:54:34Z" + }, + { + "message": "P00 INFO: check archive for prior segment 000000020000000000000003", + "timestamp": "2025-06-18T17:54:34Z" + }, + { + "message": "P00 INFO: execute non-exclusive backup stop and wait for all WAL segments to archive", + "timestamp": "2025-06-18T17:54:36Z" + }, + { + "message": "P00 INFO: backup stop archive = 000000020000000000000004, lsn = 0/4000120", + "timestamp": "2025-06-18T17:54:36Z" + }, + { + "message": "P00 INFO: check archive for segment(s) 000000020000000000000004:000000020000000000000004", + "timestamp": "2025-06-18T17:54:36Z" + }, + { + "message": "P00 INFO: new backup label = 20250618-175434F", + "timestamp": "2025-06-18T17:54:36Z" + }, + { + "message": "P00 INFO: full backup size = 30.6MB, file total = 1342", + "timestamp": "2025-06-18T17:54:36Z" + }, + { + "message": "P00 INFO: backup command end: completed successfully", + "timestamp": "2025-06-18T17:54:36Z" + }, + { + "message": "P00 INFO: expire command begin 2.55.1: --config=/opt/pgedge/configs/pgbackrest.backup.conf --exec-id=198-b17fae6e --log-level-console=info --no-log-timestamp --repo1-cipher-type=none --repo1-path=/backups/databases/storefront/n1 --repo1-retention-full=7 --repo1-retention-full-type=time --repo1-type=posix --stanza=db", + "timestamp": "2025-06-18T17:54:36Z" + }, + { + "message": "P00 INFO: repo1: time-based archive retention not met - archive logs will not be expired", + "timestamp": "2025-06-18T17:54:36Z" + }, + { + "message": "P00 INFO: expire command end: completed successfully", + "timestamp": "2025-06-18T17:54:36Z" + } + ], + "last_entry_id": "0197842d-b14d-7c69-86c1-c006a7c65318", + "scope": "database", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "task_status": "completed" + } + }, + "update task log": { + "summary": "update task log", + "description": "This is the task log of an update task. This example excludes many entries for brevity.", + "value": { + "entity_id": "storefront", + "entries": [ + { + "message": "refreshing current state", + "timestamp": "2025-06-18T17:53:19Z" + }, + { + "fields": { + "duration_ms": 8972 + }, + "message": "finished refreshing current state (took 8.972080116s)", + "timestamp": "2025-06-18T17:53:28Z" + }, + { + "fields": { + "host_id": "host-1", + "resource_id": "storefront-n1-689qacsi-backup", + "resource_type": "swarm.pgbackrest_config" + }, + "message": "creating resource swarm.pgbackrest_config::storefront-n1-689qacsi-backup", + "timestamp": "2025-06-18T17:53:29Z" + }, + { + "fields": { + "host_id": "host-2", + "resource_id": "storefront-n2-9ptayhma-backup", + "resource_type": "swarm.pgbackrest_config" + }, + "message": "creating resource swarm.pgbackrest_config::storefront-n2-9ptayhma-backup", + "timestamp": "2025-06-18T17:53:29Z" + }, + { + "fields": { + "duration_ms": 383, + "host_id": "host-3", + "resource_id": "n3", + "resource_type": "swarm.pgbackrest_stanza", + "success": true + }, + "message": "finished creating resource swarm.pgbackrest_stanza::n3 (took 383.568613ms)", + "timestamp": "2025-06-18T17:54:02Z" + }, + { + "fields": { + "duration_ms": 1181, + "host_id": "host-1", + "resource_id": "n1", + "resource_type": "swarm.pgbackrest_stanza", + "success": true + }, + "message": "finished creating resource swarm.pgbackrest_stanza::n1 (took 1.181454868s)", + "timestamp": "2025-06-18T17:54:03Z" + } + ], + "last_entry_id": "0197842d-303b-7251-b814-6d12c98e7d25", + "scope": "database", + "task_id": "0197842c-7c4f-7a8c-829e-7405c2a41c8c", + "task_status": "completed" + } + } + } + } + } + }, + "400": { + "description": "invalid_input: Bad Request response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "404": { + "description": "not_found: Not Found response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "409": { + "description": "cluster_not_initialized: Conflict response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "500": { + "description": "server_error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + } + } + } + }, + "/v1/tasks": { + "get": { + "tags": [ + "System" + ], + "summary": "List tasks", + "description": "Lists tasks across all scopes with optional filtering by scope and entity ID.", + "operationId": "list-tasks", + "parameters": [ + { + "name": "scope", + "in": "query", + "description": "Optional scope to filter tasks (database or host).", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Optional scope to filter tasks (database or host).", + "example": "database", + "enum": [ + "database", + "host" + ] + }, + "example": "database" + }, + { + "name": "entity_id", + "in": "query", + "description": "Optional entity ID to filter tasks. Requires scope to be set.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens.", + "example": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "minLength": 1, + "maxLength": 63 + }, + "example": "my-app" + }, + { + "name": "after_task_id", + "in": "query", + "description": "ID of the task to start from.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "ID of the task to start from.", + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348", + "format": "uuid" + }, + "example": "3c875a27-f6a6-4c1c-ba5f-6972fb1fc348" + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of tasks to return.", + "allowEmptyValue": true, + "schema": { + "type": "integer", + "description": "Maximum number of tasks to return.", + "example": 100, + "format": "int64" + }, + "example": 100 + }, + { + "name": "sort_order", + "in": "query", + "description": "Sort order for the tasks.", + "allowEmptyValue": true, + "schema": { + "type": "string", + "description": "Sort order for the tasks.", + "example": "ascend", + "enum": [ + "asc", + "ascend", + "ascending", + "desc", + "descend", + "descending" + ] + }, + "example": "ascend" + } + ], + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListTasksResponse" + }, + "example": { + "tasks": [ + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "database_id": "storefront", + "entity_id": "storefront", + "instance_id": "storefront-n1-689qacsi", + "scope": "database", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "node_backup" + }, + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "entity_id": "host-1", + "host_id": "host-1", + "scope": "host", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "remove_host" + } + ] + } + } + } + }, + "400": { + "description": "invalid_input: Bad Request response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "409": { + "description": "cluster_not_initialized: Conflict response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + }, + "500": { + "description": "server_error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + } + } + } + }, + "/v1/version": { + "get": { + "tags": [ + "System" + ], + "summary": "Get version", + "description": "Returns version information for this Control Plane server.", + "operationId": "get-version", + "responses": { + "200": { + "description": "OK response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionInfo" + }, + "example": { + "arch": "amd64", + "revision": "e89ae93b", + "revision_time": "2025-01-01T01:30:00Z", + "version": "1.0.0" + } + } + } + }, + "500": { + "description": "server_error: Internal Server Error response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/APIError" + }, + "example": { + "message": "A longer description of the error.", + "name": "error_name" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "APIError": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "The error message.", + "example": "A longer description of the error." + }, + "name": { + "type": "string", + "description": "The name of the error.", + "example": "error_name" + } + }, + "description": "A Control Plane API error.", + "example": { + "message": "A longer description of the error.", + "name": "error_name" + }, + "required": [ + "name", + "message" + ] + }, + "BackupConfigSpec": { + "type": "object", + "properties": { + "repositories": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BackupRepositorySpec" + }, + "description": "The repositories for this backup configuration.", + "example": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "f6b84a99-5e91-4203-be1e-131fe82e5984", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "minItems": 1 + }, + "schedules": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BackupScheduleSpec" + }, + "description": "The schedules for this backup configuration.", + "example": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ], + "maxItems": 32 + } + }, "example": { "repositories": [ { @@ -4350,7 +5052,7 @@ }, "additionalProperties": { "type": "string", - "example": "At esse ut possimus error eligendi." + "example": "Possimus error eligendi recusandae." } }, "backup_options": { @@ -4361,7 +5063,7 @@ }, "additionalProperties": { "type": "string", - "example": "Similique sed neque eos rerum quia." + "example": "Sed neque eos rerum quia." } }, "type": { @@ -5130,7 +5832,7 @@ "state": { "type": "string", "description": "Current state of the database.", - "example": "creating", + "example": "failed", "enum": [ "creating", "modifying", @@ -7704,8 +8406,6 @@ }, "description": "The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas.", "example": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696", - "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "minItems": 1 @@ -7849,6 +8549,7 @@ }, "cpus": "500m", "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696", "76f9b8c0-4958-11f0-a489-3bb29577c696" ], "memory": "500M", @@ -9533,249 +10234,36 @@ "destination_path": "/backups/container", "host_path": "/Users/user/backups/host" }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 - }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" - }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" - }, - "source_node": "n1" - } - ], - "minItems": 1, - "maxItems": 9 - }, - "orchestrator_opts": { - "$ref": "#/components/schemas/OrchestratorOpts" - }, - "port": { - "type": "integer", - "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", - "example": 5432, - "format": "int64", - "minimum": 0, - "maximum": 65535 - }, - "postgres_version": { - "type": "string", - "description": "The Postgres version in 'major.minor' format.", - "example": "17.6", - "pattern": "^\\d{2}\\.\\d{1,2}$" - }, - "postgresql_conf": { - "type": "object", - "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", - "example": { - "max_connections": 1000 - }, - "maxLength": 64, - "additionalProperties": true - }, - "restore_config": { - "$ref": "#/components/schemas/RestoreConfigSpec" - }, - "spock_version": { - "type": "string", - "description": "The major version of the Spock extension.", - "example": "5", - "pattern": "^\\d{1}$" - } - }, - "example": { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - } - ], - "schedules": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ] - }, - "cpus": "500m", - "database_name": "northwind", - "database_users": [ - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": true, - "password": "secret", - "roles": [ - "pgedge_superuser" - ], - "username": "admin" - }, - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": true, - "password": "secret", - "roles": [ - "pgedge_superuser" - ], - "username": "admin" - }, - { - "attributes": [ - "LOGIN", - "CREATEDB", - "CREATEROLE" - ], - "db_owner": true, - "password": "secret", - "roles": [ - "pgedge_superuser" - ], - "username": "admin" - } - ], - "memory": "500M", - "nodes": [ - { - "backup_config": { - "repositories": [ - { + "restore_config": { + "repository": { "azure_account": "pgedge-backups", "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "azure_endpoint": "blob.core.usgovcloudapi.net", "azure_key": "YXpLZXk=", "base_path": "/backups", "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" }, "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "gcs_endpoint": "localhost", "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "s3_endpoint": "s3.us-east-1.amazonaws.com", "s3_key": "AKIAIOSFODNN7EXAMPLE", @@ -9783,356 +10271,569 @@ "s3_region": "us-east-1", "type": "s3" }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" }, - { + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" + }, + { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 + }, + "restore_config": { + "repository": { "azure_account": "pgedge-backups", "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "azure_endpoint": "blob.core.usgovcloudapi.net", "azure_key": "YXpLZXk=", "base_path": "/backups", "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" }, "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "gcs_endpoint": "localhost", "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "s3_endpoint": "s3.us-east-1.amazonaws.com", "s3_key": "AKIAIOSFODNN7EXAMPLE", "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "s3_region": "us-east-1", "type": "s3" - } - ], - "schedules": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ] + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" }, - "cpus": "500m", - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "500M", - "name": "n1", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" - }, - "extra_networks": [ + { + "backup_config": { + "repositories": [ { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" }, - "id": "traefik-public" + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" }, { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" }, - "id": "traefik-public" + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" }, { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" }, - "id": "traefik-public" + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" } ], - "extra_volumes": [ + "schedules": [ { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" }, { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" }, { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" } ] - } - }, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 - }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" + "cpus": "500m", + "host_ids": [ + "76f9b8c0-4958-11f0-a489-3bb29577c696" + ], + "memory": "500M", + "name": "n1", + "orchestrator_opts": { + "swarm": { + "extra_labels": { + "traefik.enable": "true", + "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + }, + "extra_networks": [ + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + }, + { + "aliases": [ + "pg-db", + "db-alias" + ], + "driver_opts": { + "com.docker.network.endpoint.expose": "true" + }, + "id": "traefik-public" + } + ], + "extra_volumes": [ + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + }, + { + "destination_path": "/backups/container", + "host_path": "/Users/user/backups/host" + } + ] + } + }, + "port": 5432, + "postgres_version": "17.6", + "postgresql_conf": { + "max_connections": 1000 }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" - }, - "source_node": "n1" - }, - { - "backup_config": { - "repositories": [ - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" - }, - { + "restore_config": { + "repository": { "azure_account": "pgedge-backups", "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "azure_endpoint": "blob.core.usgovcloudapi.net", "azure_key": "YXpLZXk=", "base_path": "/backups", "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", - "storage-upload-chunk-size": "5MiB" + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" }, "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "gcs_endpoint": "localhost", "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "retention_full": 2, - "retention_full_type": "count", "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", "s3_endpoint": "s3.us-east-1.amazonaws.com", "s3_key": "AKIAIOSFODNN7EXAMPLE", "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "s3_region": "us-east-1", "type": "s3" - } - ], - "schedules": [ - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" }, - { - "cron_expression": "0 6 * * ?", - "id": "daily-full-backup", - "type": "full" - } - ] - }, - "cpus": "500m", - "host_ids": [ - "76f9b8c0-4958-11f0-a489-3bb29577c696" - ], - "memory": "500M", - "name": "n1", - "orchestrator_opts": { - "swarm": { - "extra_labels": { - "traefik.enable": "true", - "traefik.tcp.routers.mydb.rule": "HostSNI(`mydb.example.com`)" + "restore_options": { + "set": "20250505-153628F", + "target": "123456", + "type": "xid" }, - "extra_networks": [ - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - }, - { - "aliases": [ - "pg-db", - "db-alias" - ], - "driver_opts": { - "com.docker.network.endpoint.expose": "true" - }, - "id": "traefik-public" - } - ], - "extra_volumes": [ - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - }, - { - "destination_path": "/backups/container", - "host_path": "/Users/user/backups/host" - } - ] - } - }, - "port": 5432, - "postgres_version": "17.6", - "postgresql_conf": { - "max_connections": 1000 + "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "source_database_name": "northwind", + "source_node_name": "n1" + }, + "source_node": "n1" + } + ], + "minItems": 1, + "maxItems": 9 + }, + "orchestrator_opts": { + "$ref": "#/components/schemas/OrchestratorOpts" + }, + "port": { + "type": "integer", + "description": "The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature.", + "example": 5432, + "format": "int64", + "minimum": 0, + "maximum": 65535 + }, + "postgres_version": { + "type": "string", + "description": "The Postgres version in 'major.minor' format.", + "example": "17.6", + "pattern": "^\\d{2}\\.\\d{1,2}$" + }, + "postgresql_conf": { + "type": "object", + "description": "Additional postgresql.conf settings. Will be merged with the settings provided by control-plane.", + "example": { + "max_connections": 1000 + }, + "maxLength": 64, + "additionalProperties": true + }, + "restore_config": { + "$ref": "#/components/schemas/RestoreConfigSpec" + }, + "spock_version": { + "type": "string", + "description": "The major version of the Spock extension.", + "example": "5", + "pattern": "^\\d{1}$" + } + }, + "example": { + "backup_config": { + "repositories": [ + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" + }, + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" }, - "restore_config": { - "repository": { - "azure_account": "pgedge-backups", - "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "azure_endpoint": "blob.core.usgovcloudapi.net", - "azure_key": "YXpLZXk=", - "base_path": "/backups", - "custom_options": { - "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab" - }, - "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "gcs_endpoint": "localhost", - "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", - "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", - "s3_endpoint": "s3.us-east-1.amazonaws.com", - "s3_key": "AKIAIOSFODNN7EXAMPLE", - "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "s3_region": "us-east-1", - "type": "s3" + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" }, - "restore_options": { - "set": "20250505-153628F", - "target": "123456", - "type": "xid" + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + }, + { + "azure_account": "pgedge-backups", + "azure_container": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "azure_endpoint": "blob.core.usgovcloudapi.net", + "azure_key": "YXpLZXk=", + "base_path": "/backups", + "custom_options": { + "s3-kms-key-id": "1234abcd-12ab-34cd-56ef-1234567890ab", + "storage-upload-chunk-size": "5MiB" }, - "source_database_id": "76f9b8c0-4958-11f0-a489-3bb29577c696", - "source_database_name": "northwind", - "source_node_name": "n1" + "gcs_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "gcs_endpoint": "localhost", + "gcs_key": "ZXhhbXBsZSBnY3Mga2V5Cg==", + "id": "76f9b8c0-4958-11f0-a489-3bb29577c696", + "retention_full": 2, + "retention_full_type": "count", + "s3_bucket": "pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1", + "s3_endpoint": "s3.us-east-1.amazonaws.com", + "s3_key": "AKIAIOSFODNN7EXAMPLE", + "s3_key_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "s3_region": "us-east-1", + "type": "s3" + } + ], + "schedules": [ + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" }, - "source_node": "n1" + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + }, + { + "cron_expression": "0 6 * * ?", + "id": "daily-full-backup", + "type": "full" + } + ] + }, + "cpus": "500m", + "database_name": "northwind", + "database_users": [ + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" + ], + "db_owner": true, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" }, + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" + ], + "db_owner": true, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + }, + { + "attributes": [ + "LOGIN", + "CREATEDB", + "CREATEROLE" + ], + "db_owner": true, + "password": "secret", + "roles": [ + "pgedge_superuser" + ], + "username": "admin" + } + ], + "memory": "500M", + "nodes": [ { "backup_config": { "repositories": [ @@ -13253,7 +13954,7 @@ "created_at": { "type": "string", "description": "The time that the instance was created.", - "example": "1984-01-30T10:40:13Z", + "example": "2006-12-23T09:53:03Z", "format": "date-time" }, "error": { @@ -13305,7 +14006,7 @@ "updated_at": { "type": "string", "description": "The time that the instance was last modified.", - "example": "1996-05-27T17:04:41Z", + "example": "2012-08-16T06:20:51Z", "format": "date-time" } }, @@ -13618,6 +14319,53 @@ ] } }, + "ListHostTasksResponse": { + "type": "object", + "properties": { + "tasks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Task" + }, + "example": [ + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + } + ] + } + }, + "example": { + "tasks": [ + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "entity_id": "host-1", + "host_id": "host-1", + "scope": "host", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "remove_host" + } + ] + } + }, "ListHostsResponse": { "type": "object", "properties": { @@ -13920,6 +14668,84 @@ "hosts" ] }, + "ListTasksResponse": { + "type": "object", + "properties": { + "tasks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Task" + }, + "example": [ + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + }, + { + "completed_at": "2025-06-18T16:52:35Z", + "created_at": "2025-06-18T16:52:05Z", + "database_id": "storefront", + "entity_id": "storefront", + "scope": "database", + "status": "completed", + "task_id": "019783f4-75f4-71e7-85a3-c9b96b345d77", + "type": "create" + } + ] + } + }, + "example": { + "tasks": [ + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "database_id": "storefront", + "entity_id": "storefront", + "instance_id": "storefront-n1-689qacsi", + "scope": "database", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "node_backup" + }, + { + "completed_at": "2025-06-18T17:54:36Z", + "created_at": "2025-06-18T17:54:28Z", + "entity_id": "host-1", + "host_id": "host-1", + "scope": "host", + "status": "completed", + "task_id": "0197842d-9082-7496-b787-77bd2e11809f", + "type": "remove_host" + } + ] + } + }, "Listdatabasesresponse": { "type": "object", "properties": { diff --git a/api/apiv1/gen/http/openapi3.yaml b/api/apiv1/gen/http/openapi3.yaml index c37c5de2..f723be40 100644 --- a/api/apiv1/gen/http/openapi3.yaml +++ b/api/apiv1/gen/http/openapi3.yaml @@ -2728,25 +2728,105 @@ paths: example: message: A longer description of the error. name: error_name - /v1/version: + /v1/hosts/{host_id}/tasks: get: tags: - - System - summary: Get version - description: Returns version information for this Control Plane server. - operationId: get-version + - Host + summary: List host tasks + description: Lists all tasks for a host. + operationId: list-host-tasks + parameters: + - name: after_task_id + in: query + description: ID of the task to start from. + allowEmptyValue: true + schema: + type: string + description: ID of the task to start from. + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + format: uuid + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + - name: limit + in: query + description: Maximum number of tasks to return. + allowEmptyValue: true + schema: + type: integer + description: Maximum number of tasks to return. + example: 100 + format: int64 + example: 100 + - name: sort_order + in: query + description: Sort order for the tasks. + allowEmptyValue: true + schema: + type: string + description: Sort order for the tasks. + example: ascend + enum: + - asc + - ascend + - ascending + - desc + - descend + - descending + example: ascend + - name: host_id + in: path + description: ID of the host to list tasks for. + required: true + schema: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + example: host-1 responses: "200": description: OK response. content: application/json: schema: - $ref: '#/components/schemas/VersionInfo' + $ref: '#/components/schemas/ListHostTasksResponse' example: - arch: amd64 - revision: e89ae93b - revision_time: "2025-01-01T01:30:00Z" - version: 1.0.0 + tasks: + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + entity_id: host-1 + host_id: host-1 + scope: host + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: remove_host + "400": + description: 'invalid_input: Bad Request response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "404": + description: 'not_found: Not Found response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "409": + description: 'cluster_not_initialized: Conflict response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name "500": description: 'server_error: Internal Server Error response.' content: @@ -2756,3148 +2836,1612 @@ paths: example: message: A longer description of the error. name: error_name -components: - schemas: - APIError: - type: object - properties: - message: - type: string - description: The error message. - example: A longer description of the error. - name: - type: string - description: The name of the error. - example: error_name - description: A Control Plane API error. - example: - message: A longer description of the error. - name: error_name - required: - - name - - message - BackupConfigSpec: - type: object - properties: - repositories: - type: array - items: - $ref: '#/components/schemas/BackupRepositorySpec' - description: The repositories for this backup configuration. - example: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - minItems: 1 - schedules: - type: array - items: - $ref: '#/components/schemas/BackupScheduleSpec' - description: The schedules for this backup configuration. - example: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - maxItems: 32 - example: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - required: - - repositories - BackupDatabaseNodeResponse: - type: object - properties: - task: - $ref: '#/components/schemas/Task' - example: - task: - created_at: "2025-06-18T17:54:28Z" - database_id: storefront - status: pending - task_id: 0197842d-9082-7496-b787-77bd2e11809f - type: node_backup - required: - - task - BackupOptions: - type: object - properties: - annotations: - type: object - description: Annotations for the backup. - example: - key: value - additionalProperties: - type: string - example: At esse ut possimus error eligendi. - backup_options: - type: object - description: Options for the backup. - example: - archive-check: "n" - additionalProperties: + /v1/hosts/{host_id}/tasks/{task_id}: + get: + tags: + - Host + summary: Get host task + description: Returns information about a particular task for a host. + operationId: get-host-task + parameters: + - name: host_id + in: path + description: ID of the host the task belongs to. + required: true + schema: type: string - example: Similique sed neque eos rerum quia. - type: - type: string - description: The type of backup. - example: full - enum: - - full - - diff - - incr - example: - annotations: - initiated-by: backup-cron-job - backup_options: - archive-check: "n" - type: full - required: - - type - BackupRepositorySpec: - type: object - properties: - azure_account: - type: string - description: The Azure account name for this repository. Only applies when type = 'azure'. - example: pgedge-backups - minLength: 3 - maxLength: 24 - azure_container: - type: string - description: The Azure container name for this repository. Only applies when type = 'azure'. - example: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - minLength: 3 - maxLength: 63 - azure_endpoint: - type: string - description: The optional Azure endpoint for this repository. Only applies when type = 'azure'. - example: blob.core.usgovcloudapi.net - minLength: 3 - maxLength: 128 - azure_key: - type: string - description: The Azure storage account access key to use for this repository. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. - example: YXpLZXk= - maxLength: 128 - base_path: - type: string - description: The base path within the repository to store backups. Required for type = 'posix' and 'cifs'. - example: /backups - maxLength: 256 - custom_options: - type: object - description: Additional options to apply to this repository. - example: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - additionalProperties: + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + example: host-1 + - name: task_id + in: path + description: ID of the task to get. + required: true + schema: type: string - example: Quam sint iure eum ducimus quia. - gcs_bucket: - type: string - description: The GCS bucket name for this repository. Only applies when type = 'gcs'. - example: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - minLength: 3 - maxLength: 63 - gcs_endpoint: - type: string - description: The optional GCS endpoint for this repository. Only applies when type = 'gcs'. - example: localhost - minLength: 3 - maxLength: 128 - gcs_key: - type: string - description: Optional base64-encoded private key data. If omitted, pgbackrest will use the service account attached to the instance profile. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. - example: ZXhhbXBsZSBnY3Mga2V5Cg== - maxLength: 1024 - id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - retention_full: - type: integer - description: The count of full backups to retain or the time to retain full backups. - example: 2 - format: int64 - minimum: 1 - maximum: 9.999999e+06 - retention_full_type: - type: string - description: The type of measure used for retention_full. - example: count - enum: - - time - - count - s3_bucket: - type: string - description: The S3 bucket name for this repository. Only applies when type = 's3'. - example: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - minLength: 3 - maxLength: 63 - s3_endpoint: - type: string - description: The optional S3 endpoint for this repository. Only applies when type = 's3'. - example: s3.us-east-1.amazonaws.com - minLength: 3 - maxLength: 128 - s3_key: - type: string - description: An optional AWS access key ID to use for this repository. If not provided, pgbackrest will use the default credential provider chain. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. - example: AKIAIOSFODNN7EXAMPLE - maxLength: 128 - s3_key_secret: - type: string - description: The corresponding secret for the AWS access key ID in s3_key. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. - example: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - maxLength: 128 - s3_region: - type: string - description: The region of the S3 bucket for this repository. Only applies when type = 's3'. - example: us-east-1 - minLength: 1 - maxLength: 32 - type: - type: string - description: The type of this repository. - example: s3 - enum: - - s3 - - gcs - - azure - - posix - - cifs - example: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - required: - - type - BackupScheduleSpec: - type: object - properties: - cron_expression: - type: string - description: The cron expression for this schedule. - example: 0 6 * * ? - maxLength: 32 - id: - type: string - description: The unique identifier for this backup schedule. - example: daily-full-backup - maxLength: 64 - type: - type: string - description: The type of backup to take on this schedule. - example: full - enum: - - full - - incr - example: - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - required: - - id - - type - - cron_expression - CancelDatabaseTaskPayload: - type: object - properties: - database_id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - task_id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - example: - database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - task_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - required: - - database_id - - task_id - Cluster: - type: object - properties: - hosts: - type: array - items: - $ref: '#/components/schemas/Host' - description: All of the hosts in the cluster. - example: - - cohort: - cohort_id: zdjfu3tfxg1cihv3146ro3hy2 - control_available: true - member_id: lah4bsznw6kc0hp7biylmmmll - type: swarm - cpus: 16 - data_dir: /data - default_pgedge_version: - postgres_version: "17.6" - spock_version: "5" - hostname: i-0123456789abcdef.ec2.internal - id: us-east-1 - ipv4_address: 10.24.34.2 - memory: 16GB - orchestrator: swarm - status: - components: {} - state: healthy - updated_at: "2025-06-17T00:00:00Z" - supported_pgedge_versions: - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "18.1" - spock_version: "5" - - postgres_version: "16.10" - spock_version: "5" - - cohort: - cohort_id: zdjfu3tfxg1cihv3146ro3hy2 - control_available: true - member_id: cb88u9jael2psnepep5iuzb4r - type: swarm - cpus: 16 - data_dir: /data - default_pgedge_version: - postgres_version: "17.6" - spock_version: "5" - hostname: i-058731542fee493f.ec2.internal - id: ap-south-1 - ipv4_address: 10.24.35.2 - memory: 16GB - orchestrator: swarm - status: - components: {} - state: healthy - updated_at: "2025-06-17T00:00:00Z" - supported_pgedge_versions: - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "18.1" - spock_version: "5" - - postgres_version: "16.10" - spock_version: "5" - - cohort: - cohort_id: zdjfu3tfxg1cihv3146ro3hy2 - control_available: true - member_id: u7u9i3nhqunxc4wj577l6ecb0 - type: swarm - cpus: 16 - data_dir: /data - default_pgedge_version: - postgres_version: "17.6" - spock_version: "5" - hostname: i-494027b7b53f6a23.ec2.internal - id: eu-central-1 - ipv4_address: 10.24.36.2 - memory: 16GB - orchestrator: swarm - status: - components: {} - state: healthy - updated_at: "2025-06-17T00:00:00Z" - supported_pgedge_versions: - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "18.1" - spock_version: "5" - - postgres_version: "16.10" - spock_version: "5" - id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - status: - $ref: '#/components/schemas/ClusterStatus' - example: - hosts: - - cohort: - cohort_id: zdjfu3tfxg1cihv3146ro3hy2 - control_available: true - member_id: lah4bsznw6kc0hp7biylmmmll - type: swarm - cpus: 16 - data_dir: /data - default_pgedge_version: - postgres_version: "17.6" - spock_version: "5" - hostname: i-0123456789abcdef.ec2.internal - id: us-east-1 - ipv4_address: 10.24.34.2 - memory: 16GB - orchestrator: swarm - status: - components: {} - state: healthy - updated_at: "2025-06-17T00:00:00Z" - supported_pgedge_versions: - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "18.1" - spock_version: "5" - - postgres_version: "16.10" - spock_version: "5" - - cohort: - cohort_id: zdjfu3tfxg1cihv3146ro3hy2 - control_available: true - member_id: cb88u9jael2psnepep5iuzb4r - type: swarm - cpus: 16 - data_dir: /data - default_pgedge_version: - postgres_version: "17.6" - spock_version: "5" - hostname: i-058731542fee493f.ec2.internal - id: ap-south-1 - ipv4_address: 10.24.35.2 - memory: 16GB - orchestrator: swarm - status: - components: {} - state: healthy - updated_at: "2025-06-17T00:00:00Z" - supported_pgedge_versions: - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "18.1" - spock_version: "5" - - postgres_version: "16.10" - spock_version: "5" - - cohort: - cohort_id: zdjfu3tfxg1cihv3146ro3hy2 - control_available: true - member_id: u7u9i3nhqunxc4wj577l6ecb0 - type: swarm - cpus: 16 - data_dir: /data - default_pgedge_version: - postgres_version: "17.6" - spock_version: "5" - hostname: i-494027b7b53f6a23.ec2.internal - id: eu-central-1 - ipv4_address: 10.24.36.2 - memory: 16GB - orchestrator: swarm - status: - components: {} - state: healthy - updated_at: "2025-06-17T00:00:00Z" - supported_pgedge_versions: - - postgres_version: "17.6" - spock_version: "5" - - postgres_version: "18.1" - spock_version: "5" - - postgres_version: "16.10" - spock_version: "5" - id: production - status: - state: available - required: - - id - - status - - hosts - ClusterCredentials: - type: object - properties: - ca_cert: - type: string - description: The base64-encoded CA certificate for the cluster. - example: ZGE4NDdkMzMtM2FiYi00YzE2LTkzOGQtNDRkODU2ZDFlZWZlCg== - client_cert: - type: string - description: The base64-encoded etcd client certificate for the new cluster member. - example: NWM0MGMyZTAtYjAyYS00NzkxLTk0YjAtMjMyN2EyZGQ4ZDc3Cg== - client_key: - type: string - description: The base64-encoded etcd client key for the new cluster member. - example: Y2FlNjhmODQtYjE1Ni00YWYyLWFhMWEtM2FhNzI2MmVhYTM0Cg== - password: - type: string - description: The Etcd password for the new host. - example: a78v2x866zirk4o737gjdssfi - server_cert: - type: string - description: The base64-encoded etcd server certificate for the new cluster member. - example: Nzc1OGQyY2UtZjdjOC00YmE4LTk2ZmQtOWE3MjVmYmY3NDdiCg== - server_key: - type: string - description: The base64-encoded etcd server key for the new cluster member. - example: NWRhNzY1ZGUtNzJkMi00OTU3LTk4ODUtOWRiZThjOGE5MGQ3Cg== - username: - type: string - description: The Etcd username for the new host. - example: host-2 - example: - ca_cert: ZGE4NDdkMzMtM2FiYi00YzE2LTkzOGQtNDRkODU2ZDFlZWZlCg== - client_cert: NWM0MGMyZTAtYjAyYS00NzkxLTk0YjAtMjMyN2EyZGQ4ZDc3Cg== - client_key: Y2FlNjhmODQtYjE1Ni00YWYyLWFhMWEtM2FhNzI2MmVhYTM0Cg== - password: a78v2x866zirk4o737gjdssfi - server_cert: Nzc1OGQyY2UtZjdjOC00YmE4LTk2ZmQtOWE3MjVmYmY3NDdiCg== - server_key: NWRhNzY1ZGUtNzJkMi00OTU3LTk4ODUtOWRiZThjOGE5MGQ3Cg== - username: host-2 - required: - - username - - password - - ca_cert - - client_cert - - client_key - - server_cert - - server_key - ClusterJoinOptions: - type: object - properties: - credentials: - $ref: '#/components/schemas/ClusterCredentials' - leader: - $ref: '#/components/schemas/EtcdClusterMember' - example: - credentials: - ca_cert: ZGE4NDdkMzMtM2FiYi00YzE2LTkzOGQtNDRkODU2ZDFlZWZlCg== - client_cert: NWM0MGMyZTAtYjAyYS00NzkxLTk0YjAtMjMyN2EyZGQ4ZDc3Cg== - client_key: Y2FlNjhmODQtYjE1Ni00YWYyLWFhMWEtM2FhNzI2MmVhYTM0Cg== - password: a78v2x866zirk4o737gjdssfi - server_cert: Nzc1OGQyY2UtZjdjOC00YmE4LTk2ZmQtOWE3MjVmYmY3NDdiCg== - server_key: NWRhNzY1ZGUtNzJkMi00OTU3LTk4ODUtOWRiZThjOGE5MGQ3Cg== - username: host-2 - leader: - client_urls: - - http://192.168.1.1:2379 - name: host-1 - peer_urls: - - http://192.168.1.1:2380 - required: - - leader - - credentials - ClusterJoinRequest: - type: object - properties: - embedded_etcd_enabled: - type: boolean - description: True if the joining member is configured to run an embedded an etcd server. - example: true - host_id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - hostname: - type: string - description: The hostname of the host that's joining the cluster. - example: ip-10-1-0-113.ec2.internal - minLength: 3 - maxLength: 128 - ipv4_address: - type: string - description: The IPv4 address of the host that's joining the cluster. - example: 10.1.0.113 - format: ipv4 - token: - type: string - description: Token to join the cluster. - example: PGEDGE-dd440afcf5de20ef8e8cf54f6cb9f125fd55f90e64faa94b906130b31235e730-41e975f41d7ea61058f2fe2572cb52dd - pattern: ^PGEDGE-[\w]{64}-[\w]{32}$ - example: - embedded_etcd_enabled: true - host_id: host-1 - hostname: ip-10-1-0-113.ec2.internal - ipv4_address: 10.1.0.113 - token: PGEDGE-dd440afcf5de20ef8e8cf54f6cb9f125fd55f90e64faa94b906130b31235e730-41e975f41d7ea61058f2fe2572cb52dd - required: - - embedded_etcd_enabled - - token - - host_id - - hostname - - ipv4_address - ClusterJoinToken: - type: object - properties: - server_url: - type: string - description: Existing server to join - example: http://192.168.1.1:3000 - format: uri - token: - type: string - description: Token to join an existing cluster. - example: PGEDGE-dd440afcf5de20ef8e8cf54f6cb9f125fd55f90e64faa94b906130b31235e730-41e975f41d7ea61058f2fe2572cb52dd - example: - server_url: http://192.168.1.1:3000 - token: PGEDGE-dd440afcf5de20ef8e8cf54f6cb9f125fd55f90e64faa94b906130b31235e730-41e975f41d7ea61058f2fe2572cb52dd - required: - - token - - server_url - ClusterStatus: - type: object - properties: - state: - type: string - description: The current state of the cluster. - example: error - enum: - - available - - error - example: - state: error - required: - - state - ComponentStatus: - type: object - properties: - details: - type: object - description: Additional details about the component. - example: - alarms: - - '3: NOSPACE' - additionalProperties: true - error: - type: string - description: Error message from any errors that occurred during the health check. - example: failed to connect to etcd - healthy: - type: boolean - description: Indicates if the component is healthy. - example: false - example: - details: - alarms: - - '3: NOSPACE' - error: failed to connect to etcd - healthy: false - required: - - healthy - ControlPlaneGetDatabaseResponseBody: - type: object - properties: - created_at: - type: string - description: The time that the database was created. - example: "2025-01-01T01:30:00Z" - format: date-time - id: - type: string - description: Unique identifier for the database. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - instances: - $ref: '#/components/schemas/InstanceResponseBodyCollection' - spec: - $ref: '#/components/schemas/DatabaseSpec3' - state: - type: string - description: Current state of the database. - example: creating - enum: - - creating - - modifying - - available - - deleting - - degraded - - failed - - backing_up - - restoring - - unknown - tenant_id: - type: string - description: Unique identifier for the database. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - updated_at: - type: string - description: The time that the database was last updated. - example: "2025-01-01T02:30:00Z" - format: date-time - description: Get-DatabaseResponseBody result type (default view) - example: - created_at: "2025-06-18T16:52:05Z" - id: storefront - instances: - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "2025-06-18T16:52:22Z" - host_id: us-east-1 - id: storefront-n1-689qacsi - node_name: n1 - postgres: - patroni_state: running - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n3 - provider_node: n3 - status: replicating - - name: sub_n1n2 - provider_node: n2 - status: replicating - version: 4.0.10 - state: available - status_updated_at: "2025-06-18T17:58:56Z" - updated_at: "2025-06-18T17:54:36Z" - - connection_info: - hostname: i-058731542fee493f.ec2.internal - ipv4_address: 10.24.35.2 - port: 5432 - created_at: "2025-06-18T16:52:22Z" - host_id: ap-south-1 - id: storefront-n2-9ptayhma - node_name: n2 - postgres: - patroni_state: running - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n2n1 - provider_node: n1 - status: replicating - - name: sub_n2n3 - provider_node: n3 - status: replicating - version: 4.0.10 - state: available - status_updated_at: "2025-06-18T17:58:56Z" - updated_at: "2025-06-18T17:54:01Z" - - connection_info: - hostname: i-494027b7b53f6a23.ec2.internal - ipv4_address: 10.24.36.2 - port: 5432 - created_at: "2025-06-18T16:52:22Z" - host_id: eu-central-1 - id: storefront-n3-ant97dj4 - node_name: n3 - postgres: - patroni_state: running - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n3n1 - provider_node: n1 - status: replicating - - name: sub_n3n2 - provider_node: n2 - status: replicating - version: 4.0.10 - state: available - status_updated_at: "2025-06-18T17:58:56Z" - updated_at: "2025-06-18T17:54:01Z" - spec: - database_name: storefront - database_users: - - attributes: - - SUPERUSER - - LOGIN - db_owner: true - username: admin - nodes: - - host_ids: - - us-east-1 - name: n1 - - host_ids: - - ap-south-1 - name: n2 - - host_ids: - - eu-central-1 - name: n3 - port: 5432 - postgres_version: "17.6" - spock_version: "5" - state: restoring - updated_at: "2025-06-18T17:58:59Z" - required: - - id - - created_at - - updated_at - - state - CreateDatabaseRequest: - type: object - properties: - id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - spec: - $ref: '#/components/schemas/DatabaseSpec' - tenant_id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - example: - id: storefront - spec: - database_name: storefront - database_users: - - attributes: - - LOGIN - - SUPERUSER - db_owner: true - password: password - username: admin - nodes: - - host_ids: - - us-east-1 - name: n1 - - host_ids: - - ap-south-1 - name: n2 - - host_ids: - - eu-central-1 - name: n3 - port: 5432 - postgresql_conf: - max_connections: 5000 - required: - - spec - CreateDatabaseRequest2: - type: object - properties: - id: - type: string - description: Unique identifier for the database. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - spec: - $ref: '#/components/schemas/DatabaseSpec2' - tenant_id: - type: string - description: Unique identifier for the databases's owner. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - example: - id: storefront - spec: - database_name: storefront - database_users: - - attributes: - - LOGIN - - SUPERUSER - db_owner: true - password: password - username: admin - nodes: - - host_ids: - - us-east-1 - name: n1 - - host_ids: - - ap-south-1 - name: n2 - - host_ids: - - eu-central-1 - name: n3 - port: 5432 - postgresql_conf: - max_connections: 5000 - required: - - spec - CreateDatabaseResponse: - type: object - properties: - database: - $ref: '#/components/schemas/Database' - task: - $ref: '#/components/schemas/Task' - example: - database: - created_at: "2025-06-18T16:52:05Z" - id: storefront - spec: - database_name: storefront - database_users: - - attributes: - - SUPERUSER - - LOGIN - db_owner: true - username: admin - nodes: - - host_ids: - - us-east-1 - name: n1 - - host_ids: - - ap-south-1 - name: n2 - - host_ids: - - eu-central-1 - name: n3 - port: 5432 - postgres_version: "17.6" - spock_version: "5" - state: creating - updated_at: "2025-06-18T16:52:05Z" - task: - created_at: "2025-06-18T16:52:05Z" - database_id: storefront - status: pending - task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 - type: create - required: - - task - - database - Database: - type: object - properties: - created_at: - type: string - description: The time that the database was created. - example: "2025-01-01T01:30:00Z" - format: date-time - id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - instances: - $ref: '#/components/schemas/InstanceCollection' - spec: - $ref: '#/components/schemas/DatabaseSpec' - state: - type: string - description: Current state of the database. - example: deleting - enum: - - creating - - modifying - - available - - deleting - - degraded - - failed - - backing_up - - restoring - - unknown - tenant_id: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - updated_at: - type: string - description: The time that the database was last updated. - example: "2025-01-01T02:30:00Z" - format: date-time - example: - created_at: "2025-01-01T01:30:00Z" - id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - instances: - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - spec: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - database_name: northwind - database_users: - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - memory: 500M - nodes: - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - spock_version: "5" - state: backing_up - tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 - updated_at: "2025-01-01T02:30:00Z" - required: - - id - - created_at - - updated_at - - state - DatabaseCollection: - type: array - items: - $ref: '#/components/schemas/Database' - example: - - created_at: "2025-01-01T01:30:00Z" - id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - instances: - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - spec: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - database_name: northwind - database_users: - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - memory: 500M - nodes: - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - spock_version: "5" - state: creating - tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 - updated_at: "2025-01-01T02:30:00Z" - - created_at: "2025-01-01T01:30:00Z" - id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - instances: - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - - connection_info: - hostname: i-0123456789abcdef.ec2.internal - ipv4_address: 10.24.34.2 - port: 5432 - created_at: "1987-03-24T21:22:02Z" - error: 'failed to get patroni status: connection refused' - host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec - id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d - node_name: n1 - postgres: - patroni_paused: true - patroni_state: unknown - pending_restart: false - role: primary - version: "18.1" - spock: - read_only: "off" - subscriptions: - - name: sub_n1n2 - provider_node: n2 - status: down - - name: sub_n1n2 - provider_node: n2 - status: down - version: 4.10.0 - state: creating - status_updated_at: "1974-12-13T04:15:04Z" - updated_at: "2006-10-18T16:07:16Z" - spec: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - database_name: northwind - database_users: - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - memory: 500M - nodes: - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 + description: ID of the task to get. + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + format: uuid + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + responses: + "200": + description: OK response. + content: + application/json: + schema: + $ref: '#/components/schemas/Task' + example: + completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + "400": + description: 'invalid_input: Bad Request response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "404": + description: 'not_found: Not Found response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "409": + description: 'cluster_not_initialized: Conflict response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "500": + description: 'server_error: Internal Server Error response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + /v1/hosts/{host_id}/tasks/{task_id}/logs: + get: + tags: + - Host + summary: Get host task logs + description: Returns the log of a particular task for a host. + operationId: get-host-task-log + parameters: + - name: after_entry_id + in: query + description: ID of the entry to start from. + allowEmptyValue: true + schema: + type: string + description: ID of the entry to start from. + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + format: uuid + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + - name: limit + in: query + description: Maximum number of entries to return. + allowEmptyValue: true + schema: + type: integer + description: Maximum number of entries to return. + example: 100 + format: int64 + example: 100 + - name: host_id + in: path + description: ID of the host to get the task logs for. + required: true + schema: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + example: host-1 + - name: task_id + in: path + description: ID of the task to get the logs for. + required: true + schema: + type: string + description: ID of the task to get the logs for. + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + format: uuid + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + responses: + "200": + description: OK response. + content: + application/json: + schema: + $ref: '#/components/schemas/TaskLog' + examples: + node_backup task log: + summary: node_backup task log + description: The task log from a 'node_backup' task. These messages are produced by pgbackrest. + value: + entity_id: storefront + entries: + - message: 'P00 INFO: backup command begin 2.55.1: --config=/opt/pgedge/configs/pgbackrest.backup.conf --exec-id=198-b17fae6e --log-level-console=info --no-log-timestamp --pg1-path=/opt/pgedge/data/pgdata --pg1-user=pgedge --repo1-cipher-type=none --repo1-path=/backups/databases/storefront/n1 --repo1-retention-full=7 --repo1-retention-full-type=time --repo1-type=posix --stanza=db --start-fast --type=full' + timestamp: "2025-06-18T17:54:34Z" + - message: 'P00 INFO: execute non-exclusive backup start: backup begins after the requested immediate checkpoint completes' + timestamp: "2025-06-18T17:54:34Z" + - message: 'P00 INFO: backup start archive = 000000020000000000000004, lsn = 0/4000028' + timestamp: "2025-06-18T17:54:34Z" + - message: 'P00 INFO: check archive for prior segment 000000020000000000000003' + timestamp: "2025-06-18T17:54:34Z" + - message: 'P00 INFO: execute non-exclusive backup stop and wait for all WAL segments to archive' + timestamp: "2025-06-18T17:54:36Z" + - message: 'P00 INFO: backup stop archive = 000000020000000000000004, lsn = 0/4000120' + timestamp: "2025-06-18T17:54:36Z" + - message: 'P00 INFO: check archive for segment(s) 000000020000000000000004:000000020000000000000004' + timestamp: "2025-06-18T17:54:36Z" + - message: 'P00 INFO: new backup label = 20250618-175434F' + timestamp: "2025-06-18T17:54:36Z" + - message: 'P00 INFO: full backup size = 30.6MB, file total = 1342' + timestamp: "2025-06-18T17:54:36Z" + - message: 'P00 INFO: backup command end: completed successfully' + timestamp: "2025-06-18T17:54:36Z" + - message: 'P00 INFO: expire command begin 2.55.1: --config=/opt/pgedge/configs/pgbackrest.backup.conf --exec-id=198-b17fae6e --log-level-console=info --no-log-timestamp --repo1-cipher-type=none --repo1-path=/backups/databases/storefront/n1 --repo1-retention-full=7 --repo1-retention-full-type=time --repo1-type=posix --stanza=db' + timestamp: "2025-06-18T17:54:36Z" + - message: 'P00 INFO: repo1: time-based archive retention not met - archive logs will not be expired' + timestamp: "2025-06-18T17:54:36Z" + - message: 'P00 INFO: expire command end: completed successfully' + timestamp: "2025-06-18T17:54:36Z" + last_entry_id: 0197842d-b14d-7c69-86c1-c006a7c65318 + scope: database + task_id: 0197842d-9082-7496-b787-77bd2e11809f + task_status: completed + update task log: + summary: update task log + description: This is the task log of an update task. This example excludes many entries for brevity. + value: + entity_id: storefront + entries: + - message: refreshing current state + timestamp: "2025-06-18T17:53:19Z" + - fields: + duration_ms: 8972 + message: finished refreshing current state (took 8.972080116s) + timestamp: "2025-06-18T17:53:28Z" + - fields: + host_id: host-1 + resource_id: storefront-n1-689qacsi-backup + resource_type: swarm.pgbackrest_config + message: creating resource swarm.pgbackrest_config::storefront-n1-689qacsi-backup + timestamp: "2025-06-18T17:53:29Z" + - fields: + host_id: host-2 + resource_id: storefront-n2-9ptayhma-backup + resource_type: swarm.pgbackrest_config + message: creating resource swarm.pgbackrest_config::storefront-n2-9ptayhma-backup + timestamp: "2025-06-18T17:53:29Z" + - fields: + duration_ms: 383 + host_id: host-3 + resource_id: n3 + resource_type: swarm.pgbackrest_stanza + success: true + message: finished creating resource swarm.pgbackrest_stanza::n3 (took 383.568613ms) + timestamp: "2025-06-18T17:54:02Z" + - fields: + duration_ms: 1181 + host_id: host-1 + resource_id: n1 + resource_type: swarm.pgbackrest_stanza + success: true + message: finished creating resource swarm.pgbackrest_stanza::n1 (took 1.181454868s) + timestamp: "2025-06-18T17:54:03Z" + last_entry_id: 0197842d-303b-7251-b814-6d12c98e7d25 + scope: database + task_id: 0197842c-7c4f-7a8c-829e-7405c2a41c8c + task_status: completed + "400": + description: 'invalid_input: Bad Request response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "404": + description: 'not_found: Not Found response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "409": + description: 'cluster_not_initialized: Conflict response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "500": + description: 'server_error: Internal Server Error response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + /v1/tasks: + get: + tags: + - System + summary: List tasks + description: Lists tasks across all scopes with optional filtering by scope and entity ID. + operationId: list-tasks + parameters: + - name: scope + in: query + description: Optional scope to filter tasks (database or host). + allowEmptyValue: true + schema: + type: string + description: Optional scope to filter tasks (database or host). + example: database + enum: + - database + - host + example: database + - name: entity_id + in: query + description: Optional entity ID to filter tasks. Requires scope to be set. + allowEmptyValue: true + schema: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + example: my-app + - name: after_task_id + in: query + description: ID of the task to start from. + allowEmptyValue: true + schema: + type: string + description: ID of the task to start from. + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + format: uuid + example: 3c875a27-f6a6-4c1c-ba5f-6972fb1fc348 + - name: limit + in: query + description: Maximum number of tasks to return. + allowEmptyValue: true + schema: + type: integer + description: Maximum number of tasks to return. + example: 100 + format: int64 + example: 100 + - name: sort_order + in: query + description: Sort order for the tasks. + allowEmptyValue: true + schema: + type: string + description: Sort order for the tasks. + example: ascend + enum: + - asc + - ascend + - ascending + - desc + - descend + - descending + example: ascend + responses: + "200": + description: OK response. + content: + application/json: + schema: + $ref: '#/components/schemas/ListTasksResponse' + example: + tasks: + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + database_id: storefront + entity_id: storefront + instance_id: storefront-n1-689qacsi + scope: database + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: node_backup + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + entity_id: host-1 + host_id: host-1 + scope: host + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: remove_host + "400": + description: 'invalid_input: Bad Request response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "409": + description: 'cluster_not_initialized: Conflict response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + "500": + description: 'server_error: Internal Server Error response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name + /v1/version: + get: + tags: + - System + summary: Get version + description: Returns version information for this Control Plane server. + operationId: get-version + responses: + "200": + description: OK response. + content: + application/json: + schema: + $ref: '#/components/schemas/VersionInfo' + example: + arch: amd64 + revision: e89ae93b + revision_time: "2025-01-01T01:30:00Z" + version: 1.0.0 + "500": + description: 'server_error: Internal Server Error response.' + content: + application/json: + schema: + $ref: '#/components/schemas/APIError' + example: + message: A longer description of the error. + name: error_name +components: + schemas: + APIError: + type: object + properties: + message: + type: string + description: The error message. + example: A longer description of the error. + name: + type: string + description: The name of the error. + example: error_name + description: A Control Plane API error. + example: + message: A longer description of the error. + name: error_name + required: + - name + - message + BackupConfigSpec: + type: object + properties: + repositories: + type: array + items: + $ref: '#/components/schemas/BackupRepositorySpec' + description: The repositories for this backup configuration. + example: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + minItems: 1 + schedules: + type: array + items: + $ref: '#/components/schemas/BackupScheduleSpec' + description: The schedules for this backup configuration. + example: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + maxItems: 32 + example: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + required: + - repositories + BackupDatabaseNodeResponse: + type: object + properties: + task: + $ref: '#/components/schemas/Task' + example: + task: + created_at: "2025-06-18T17:54:28Z" + database_id: storefront + status: pending + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: node_backup + required: + - task + BackupOptions: + type: object + properties: + annotations: + type: object + description: Annotations for the backup. + example: + key: value + additionalProperties: + type: string + example: Possimus error eligendi recusandae. + backup_options: + type: object + description: Options for the backup. + example: + archive-check: "n" + additionalProperties: + type: string + example: Sed neque eos rerum quia. + type: + type: string + description: The type of backup. + example: full + enum: + - full + - diff + - incr + example: + annotations: + initiated-by: backup-cron-job + backup_options: + archive-check: "n" + type: full + required: + - type + BackupRepositorySpec: + type: object + properties: + azure_account: + type: string + description: The Azure account name for this repository. Only applies when type = 'azure'. + example: pgedge-backups + minLength: 3 + maxLength: 24 + azure_container: + type: string + description: The Azure container name for this repository. Only applies when type = 'azure'. + example: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + minLength: 3 + maxLength: 63 + azure_endpoint: + type: string + description: The optional Azure endpoint for this repository. Only applies when type = 'azure'. + example: blob.core.usgovcloudapi.net + minLength: 3 + maxLength: 128 + azure_key: + type: string + description: The Azure storage account access key to use for this repository. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. + example: YXpLZXk= + maxLength: 128 + base_path: + type: string + description: The base path within the repository to store backups. Required for type = 'posix' and 'cifs'. + example: /backups + maxLength: 256 + custom_options: + type: object + description: Additional options to apply to this repository. + example: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + additionalProperties: + type: string + example: Quam sint iure eum ducimus quia. + gcs_bucket: + type: string + description: The GCS bucket name for this repository. Only applies when type = 'gcs'. + example: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + minLength: 3 + maxLength: 63 + gcs_endpoint: + type: string + description: The optional GCS endpoint for this repository. Only applies when type = 'gcs'. + example: localhost + minLength: 3 + maxLength: 128 + gcs_key: + type: string + description: Optional base64-encoded private key data. If omitted, pgbackrest will use the service account attached to the instance profile. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. + example: ZXhhbXBsZSBnY3Mga2V5Cg== + maxLength: 1024 + id: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + retention_full: + type: integer + description: The count of full backups to retain or the time to retain full backups. + example: 2 + format: int64 + minimum: 1 + maximum: 9.999999e+06 + retention_full_type: + type: string + description: The type of measure used for retention_full. + example: count + enum: + - time + - count + s3_bucket: + type: string + description: The S3 bucket name for this repository. Only applies when type = 's3'. + example: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + minLength: 3 + maxLength: 63 + s3_endpoint: + type: string + description: The optional S3 endpoint for this repository. Only applies when type = 's3'. + example: s3.us-east-1.amazonaws.com + minLength: 3 + maxLength: 128 + s3_key: + type: string + description: An optional AWS access key ID to use for this repository. If not provided, pgbackrest will use the default credential provider chain. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. + example: AKIAIOSFODNN7EXAMPLE + maxLength: 128 + s3_key_secret: + type: string + description: The corresponding secret for the AWS access key ID in s3_key. This field will be excluded from the response of all endpoints. It can also be omitted from update requests to keep the current value. + example: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + maxLength: 128 + s3_region: + type: string + description: The region of the S3 bucket for this repository. Only applies when type = 's3'. + example: us-east-1 + minLength: 1 + maxLength: 32 + type: + type: string + description: The type of this repository. + example: s3 + enum: + - s3 + - gcs + - azure + - posix + - cifs + example: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + required: + - type + BackupScheduleSpec: + type: object + properties: + cron_expression: + type: string + description: The cron expression for this schedule. + example: 0 6 * * ? + maxLength: 32 + id: + type: string + description: The unique identifier for this backup schedule. + example: daily-full-backup + maxLength: 64 + type: + type: string + description: The type of backup to take on this schedule. + example: full + enum: + - full + - incr + example: + cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + required: + - id + - type + - cron_expression + CancelDatabaseTaskPayload: + type: object + properties: + database_id: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + task_id: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + example: + database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + task_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + required: + - database_id + - task_id + Cluster: + type: object + properties: + hosts: + type: array + items: + $ref: '#/components/schemas/Host' + description: All of the hosts in the cluster. + example: + - cohort: + cohort_id: zdjfu3tfxg1cihv3146ro3hy2 + control_available: true + member_id: lah4bsznw6kc0hp7biylmmmll + type: swarm + cpus: 16 + data_dir: /data + default_pgedge_version: postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 + spock_version: "5" + hostname: i-0123456789abcdef.ec2.internal + id: us-east-1 + ipv4_address: 10.24.34.2 + memory: 16GB + orchestrator: swarm + status: + components: {} + state: healthy + updated_at: "2025-06-17T00:00:00Z" + supported_pgedge_versions: + - postgres_version: "17.6" + spock_version: "5" + - postgres_version: "18.1" + spock_version: "5" + - postgres_version: "16.10" + spock_version: "5" + - cohort: + cohort_id: zdjfu3tfxg1cihv3146ro3hy2 + control_available: true + member_id: cb88u9jael2psnepep5iuzb4r + type: swarm + cpus: 16 + data_dir: /data + default_pgedge_version: postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - spock_version: "5" - state: creating - tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 - updated_at: "2025-01-01T02:30:00Z" - DatabaseNodeSpec: + spock_version: "5" + hostname: i-058731542fee493f.ec2.internal + id: ap-south-1 + ipv4_address: 10.24.35.2 + memory: 16GB + orchestrator: swarm + status: + components: {} + state: healthy + updated_at: "2025-06-17T00:00:00Z" + supported_pgedge_versions: + - postgres_version: "17.6" + spock_version: "5" + - postgres_version: "18.1" + spock_version: "5" + - postgres_version: "16.10" + spock_version: "5" + - cohort: + cohort_id: zdjfu3tfxg1cihv3146ro3hy2 + control_available: true + member_id: u7u9i3nhqunxc4wj577l6ecb0 + type: swarm + cpus: 16 + data_dir: /data + default_pgedge_version: + postgres_version: "17.6" + spock_version: "5" + hostname: i-494027b7b53f6a23.ec2.internal + id: eu-central-1 + ipv4_address: 10.24.36.2 + memory: 16GB + orchestrator: swarm + status: + components: {} + state: healthy + updated_at: "2025-06-17T00:00:00Z" + supported_pgedge_versions: + - postgres_version: "17.6" + spock_version: "5" + - postgres_version: "18.1" + spock_version: "5" + - postgres_version: "16.10" + spock_version: "5" + id: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + status: + $ref: '#/components/schemas/ClusterStatus' + example: + hosts: + - cohort: + cohort_id: zdjfu3tfxg1cihv3146ro3hy2 + control_available: true + member_id: lah4bsznw6kc0hp7biylmmmll + type: swarm + cpus: 16 + data_dir: /data + default_pgedge_version: + postgres_version: "17.6" + spock_version: "5" + hostname: i-0123456789abcdef.ec2.internal + id: us-east-1 + ipv4_address: 10.24.34.2 + memory: 16GB + orchestrator: swarm + status: + components: {} + state: healthy + updated_at: "2025-06-17T00:00:00Z" + supported_pgedge_versions: + - postgres_version: "17.6" + spock_version: "5" + - postgres_version: "18.1" + spock_version: "5" + - postgres_version: "16.10" + spock_version: "5" + - cohort: + cohort_id: zdjfu3tfxg1cihv3146ro3hy2 + control_available: true + member_id: cb88u9jael2psnepep5iuzb4r + type: swarm + cpus: 16 + data_dir: /data + default_pgedge_version: + postgres_version: "17.6" + spock_version: "5" + hostname: i-058731542fee493f.ec2.internal + id: ap-south-1 + ipv4_address: 10.24.35.2 + memory: 16GB + orchestrator: swarm + status: + components: {} + state: healthy + updated_at: "2025-06-17T00:00:00Z" + supported_pgedge_versions: + - postgres_version: "17.6" + spock_version: "5" + - postgres_version: "18.1" + spock_version: "5" + - postgres_version: "16.10" + spock_version: "5" + - cohort: + cohort_id: zdjfu3tfxg1cihv3146ro3hy2 + control_available: true + member_id: u7u9i3nhqunxc4wj577l6ecb0 + type: swarm + cpus: 16 + data_dir: /data + default_pgedge_version: + postgres_version: "17.6" + spock_version: "5" + hostname: i-494027b7b53f6a23.ec2.internal + id: eu-central-1 + ipv4_address: 10.24.36.2 + memory: 16GB + orchestrator: swarm + status: + components: {} + state: healthy + updated_at: "2025-06-17T00:00:00Z" + supported_pgedge_versions: + - postgres_version: "17.6" + spock_version: "5" + - postgres_version: "18.1" + spock_version: "5" + - postgres_version: "16.10" + spock_version: "5" + id: production + status: + state: available + required: + - id + - status + - hosts + ClusterCredentials: type: object properties: - backup_config: - $ref: '#/components/schemas/BackupConfigSpec' - cpus: + ca_cert: type: string - description: The number of CPUs to allocate for the database on this node and to use for tuning Postgres. It can include the SI suffix 'm', e.g. '500m' for 500 millicpus. Cannot allocate units smaller than 1m. Defaults to the number of available CPUs on the host if 0 or unspecified. Cannot allocate more CPUs than are available on the host. Whether this limit is enforced depends on the orchestrator. - example: 500m - pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ - host_ids: - type: array - items: - type: string - description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. - example: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - minItems: 1 - memory: + description: The base64-encoded CA certificate for the cluster. + example: ZGE4NDdkMzMtM2FiYi00YzE2LTkzOGQtNDRkODU2ZDFlZWZlCg== + client_cert: + type: string + description: The base64-encoded etcd client certificate for the new cluster member. + example: NWM0MGMyZTAtYjAyYS00NzkxLTk0YjAtMjMyN2EyZGQ4ZDc3Cg== + client_key: + type: string + description: The base64-encoded etcd client key for the new cluster member. + example: Y2FlNjhmODQtYjE1Ni00YWYyLWFhMWEtM2FhNzI2MmVhYTM0Cg== + password: + type: string + description: The Etcd password for the new host. + example: a78v2x866zirk4o737gjdssfi + server_cert: + type: string + description: The base64-encoded etcd server certificate for the new cluster member. + example: Nzc1OGQyY2UtZjdjOC00YmE4LTk2ZmQtOWE3MjVmYmY3NDdiCg== + server_key: + type: string + description: The base64-encoded etcd server key for the new cluster member. + example: NWRhNzY1ZGUtNzJkMi00OTU3LTk4ODUtOWRiZThjOGE5MGQ3Cg== + username: + type: string + description: The Etcd username for the new host. + example: host-2 + example: + ca_cert: ZGE4NDdkMzMtM2FiYi00YzE2LTkzOGQtNDRkODU2ZDFlZWZlCg== + client_cert: NWM0MGMyZTAtYjAyYS00NzkxLTk0YjAtMjMyN2EyZGQ4ZDc3Cg== + client_key: Y2FlNjhmODQtYjE1Ni00YWYyLWFhMWEtM2FhNzI2MmVhYTM0Cg== + password: a78v2x866zirk4o737gjdssfi + server_cert: Nzc1OGQyY2UtZjdjOC00YmE4LTk2ZmQtOWE3MjVmYmY3NDdiCg== + server_key: NWRhNzY1ZGUtNzJkMi00OTU3LTk4ODUtOWRiZThjOGE5MGQ3Cg== + username: host-2 + required: + - username + - password + - ca_cert + - client_cert + - client_key + - server_cert + - server_key + ClusterJoinOptions: + type: object + properties: + credentials: + $ref: '#/components/schemas/ClusterCredentials' + leader: + $ref: '#/components/schemas/EtcdClusterMember' + example: + credentials: + ca_cert: ZGE4NDdkMzMtM2FiYi00YzE2LTkzOGQtNDRkODU2ZDFlZWZlCg== + client_cert: NWM0MGMyZTAtYjAyYS00NzkxLTk0YjAtMjMyN2EyZGQ4ZDc3Cg== + client_key: Y2FlNjhmODQtYjE1Ni00YWYyLWFhMWEtM2FhNzI2MmVhYTM0Cg== + password: a78v2x866zirk4o737gjdssfi + server_cert: Nzc1OGQyY2UtZjdjOC00YmE4LTk2ZmQtOWE3MjVmYmY3NDdiCg== + server_key: NWRhNzY1ZGUtNzJkMi00OTU3LTk4ODUtOWRiZThjOGE5MGQ3Cg== + username: host-2 + leader: + client_urls: + - http://192.168.1.1:2379 + name: host-1 + peer_urls: + - http://192.168.1.1:2380 + required: + - leader + - credentials + ClusterJoinRequest: + type: object + properties: + embedded_etcd_enabled: + type: boolean + description: True if the joining member is configured to run an embedded an etcd server. + example: true + host_id: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + hostname: + type: string + description: The hostname of the host that's joining the cluster. + example: ip-10-1-0-113.ec2.internal + minLength: 3 + maxLength: 128 + ipv4_address: + type: string + description: The IPv4 address of the host that's joining the cluster. + example: 10.1.0.113 + format: ipv4 + token: + type: string + description: Token to join the cluster. + example: PGEDGE-dd440afcf5de20ef8e8cf54f6cb9f125fd55f90e64faa94b906130b31235e730-41e975f41d7ea61058f2fe2572cb52dd + pattern: ^PGEDGE-[\w]{64}-[\w]{32}$ + example: + embedded_etcd_enabled: true + host_id: host-1 + hostname: ip-10-1-0-113.ec2.internal + ipv4_address: 10.1.0.113 + token: PGEDGE-dd440afcf5de20ef8e8cf54f6cb9f125fd55f90e64faa94b906130b31235e730-41e975f41d7ea61058f2fe2572cb52dd + required: + - embedded_etcd_enabled + - token + - host_id + - hostname + - ipv4_address + ClusterJoinToken: + type: object + properties: + server_url: type: string - description: The amount of memory in SI or IEC notation to allocate for the database on this node and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. - example: 500M - maxLength: 16 - name: + description: Existing server to join + example: http://192.168.1.1:3000 + format: uri + token: type: string - description: The name of the database node. - example: n1 - pattern: n[0-9]+ - orchestrator_opts: - $ref: '#/components/schemas/OrchestratorOpts' - port: - type: integer - description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. - example: 5432 - format: int64 - minimum: 0 - maximum: 65535 - postgres_version: + description: Token to join an existing cluster. + example: PGEDGE-dd440afcf5de20ef8e8cf54f6cb9f125fd55f90e64faa94b906130b31235e730-41e975f41d7ea61058f2fe2572cb52dd + example: + server_url: http://192.168.1.1:3000 + token: PGEDGE-dd440afcf5de20ef8e8cf54f6cb9f125fd55f90e64faa94b906130b31235e730-41e975f41d7ea61058f2fe2572cb52dd + required: + - token + - server_url + ClusterStatus: + type: object + properties: + state: type: string - description: The Postgres version for this node in 'major.minor' format. Overrides the Postgres version set in the DatabaseSpec. - example: "17.6" - pattern: ^\d{2}\.\d{1,2}$ - postgresql_conf: + description: The current state of the cluster. + example: error + enum: + - available + - error + example: + state: error + required: + - state + ComponentStatus: + type: object + properties: + details: type: object - description: Additional postgresql.conf settings for this particular node. Will be merged with the settings provided by control-plane. + description: Additional details about the component. example: - max_connections: 1000 + alarms: + - '3: NOSPACE' additionalProperties: true - restore_config: - $ref: '#/components/schemas/RestoreConfigSpec' - source_node: + error: type: string - description: The name of the source node to use for sync. This is typically the node (like 'n1') from which the data will be copied to initialize this new node. - example: n1 + description: Error message from any errors that occurred during the health check. + example: failed to connect to etcd + healthy: + type: boolean + description: Indicates if the component is healthy. + example: false example: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - source_node: n1 + details: + alarms: + - '3: NOSPACE' + error: failed to connect to etcd + healthy: false required: - - name - - host_ids - DatabaseNodeSpec2: + - healthy + ControlPlaneGetDatabaseResponseBody: type: object properties: - backup_config: - $ref: '#/components/schemas/BackupConfigSpec' - cpus: - type: string - description: The number of CPUs to allocate for the database on this node and to use for tuning Postgres. It can include the SI suffix 'm', e.g. '500m' for 500 millicpus. Cannot allocate units smaller than 1m. Defaults to the number of available CPUs on the host if 0 or unspecified. Cannot allocate more CPUs than are available on the host. Whether this limit is enforced depends on the orchestrator. - example: 500m - pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ - host_ids: - type: array - items: - type: string - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. - example: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - minItems: 1 - memory: + created_at: type: string - description: The amount of memory in SI or IEC notation to allocate for the database on this node and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. - example: 500M - maxLength: 16 - name: + description: The time that the database was created. + example: "2025-01-01T01:30:00Z" + format: date-time + id: type: string - description: The name of the database node. - example: n1 - pattern: n[0-9]+ - orchestrator_opts: - $ref: '#/components/schemas/OrchestratorOpts' - port: - type: integer - description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. - example: 5432 - format: int64 - minimum: 0 - maximum: 65535 - postgres_version: + description: Unique identifier for the database. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + instances: + $ref: '#/components/schemas/InstanceResponseBodyCollection' + spec: + $ref: '#/components/schemas/DatabaseSpec3' + state: type: string - description: The Postgres version for this node in 'major.minor' format. Overrides the Postgres version set in the DatabaseSpec. - example: "17.6" - pattern: ^\d{2}\.\d{1,2}$ - postgresql_conf: - type: object - description: Additional postgresql.conf settings for this particular node. Will be merged with the settings provided by control-plane. - example: - max_connections: 1000 - additionalProperties: true - restore_config: - $ref: '#/components/schemas/RestoreConfigSpec' - source_node: + description: Current state of the database. + example: failed + enum: + - creating + - modifying + - available + - deleting + - degraded + - failed + - backing_up + - restoring + - unknown + tenant_id: type: string - description: The name of the source node to use for sync. This is typically the node (like 'n1') from which the data will be copied to initialize this new node. - example: n1 + description: Unique identifier for the database. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + updated_at: + type: string + description: The time that the database was last updated. + example: "2025-01-01T02:30:00Z" + format: date-time + description: Get-DatabaseResponseBody result type (default view) example: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 + created_at: "2025-06-18T16:52:05Z" + id: storefront + instances: + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "2025-06-18T16:52:22Z" + host_id: us-east-1 + id: storefront-n1-689qacsi + node_name: n1 + postgres: + patroni_state: running + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n3 + provider_node: n3 + status: replicating + - name: sub_n1n2 + provider_node: n2 + status: replicating + version: 4.0.10 + state: available + status_updated_at: "2025-06-18T17:58:56Z" + updated_at: "2025-06-18T17:54:36Z" + - connection_info: + hostname: i-058731542fee493f.ec2.internal + ipv4_address: 10.24.35.2 + port: 5432 + created_at: "2025-06-18T16:52:22Z" + host_id: ap-south-1 + id: storefront-n2-9ptayhma + node_name: n2 + postgres: + patroni_state: running + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n2n1 + provider_node: n1 + status: replicating + - name: sub_n2n3 + provider_node: n3 + status: replicating + version: 4.0.10 + state: available + status_updated_at: "2025-06-18T17:58:56Z" + updated_at: "2025-06-18T17:54:01Z" + - connection_info: + hostname: i-494027b7b53f6a23.ec2.internal + ipv4_address: 10.24.36.2 + port: 5432 + created_at: "2025-06-18T16:52:22Z" + host_id: eu-central-1 + id: storefront-n3-ant97dj4 + node_name: n3 + postgres: + patroni_state: running + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n3n1 + provider_node: n1 + status: replicating + - name: sub_n3n2 + provider_node: n2 + status: replicating + version: 4.0.10 + state: available + status_updated_at: "2025-06-18T17:58:56Z" + updated_at: "2025-06-18T17:54:01Z" + spec: + database_name: storefront + database_users: + - attributes: + - SUPERUSER + - LOGIN + db_owner: true + username: admin + nodes: + - host_ids: + - us-east-1 + name: n1 + - host_ids: + - ap-south-1 + name: n2 + - host_ids: + - eu-central-1 + name: n3 + port: 5432 + postgres_version: "17.6" + spock_version: "5" + state: restoring + updated_at: "2025-06-18T17:58:59Z" required: - - name - - host_ids - DatabaseNodeSpec3: + - id + - created_at + - updated_at + - state + CreateDatabaseRequest: type: object properties: - backup_config: - $ref: '#/components/schemas/BackupConfigSpec' - cpus: - type: string - description: The number of CPUs to allocate for the database on this node and to use for tuning Postgres. It can include the SI suffix 'm', e.g. '500m' for 500 millicpus. Cannot allocate units smaller than 1m. Defaults to the number of available CPUs on the host if 0 or unspecified. Cannot allocate more CPUs than are available on the host. Whether this limit is enforced depends on the orchestrator. - example: 500m - pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ - host_ids: - type: array - items: - type: string - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. - example: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - minItems: 1 - memory: + id: type: string - description: The amount of memory in SI or IEC notation to allocate for the database on this node and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. - example: 500M - maxLength: 16 - name: + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + spec: + $ref: '#/components/schemas/DatabaseSpec' + tenant_id: type: string - description: The name of the database node. - example: n1 - pattern: n[0-9]+ - orchestrator_opts: - $ref: '#/components/schemas/OrchestratorOpts' - port: - type: integer - description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. - example: 5432 - format: int64 - minimum: 0 - maximum: 65535 - postgres_version: + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + example: + id: storefront + spec: + database_name: storefront + database_users: + - attributes: + - LOGIN + - SUPERUSER + db_owner: true + password: password + username: admin + nodes: + - host_ids: + - us-east-1 + name: n1 + - host_ids: + - ap-south-1 + name: n2 + - host_ids: + - eu-central-1 + name: n3 + port: 5432 + postgresql_conf: + max_connections: 5000 + required: + - spec + CreateDatabaseRequest2: + type: object + properties: + id: type: string - description: The Postgres version for this node in 'major.minor' format. Overrides the Postgres version set in the DatabaseSpec. - example: "17.6" - pattern: ^\d{2}\.\d{1,2}$ - postgresql_conf: - type: object - description: Additional postgresql.conf settings for this particular node. Will be merged with the settings provided by control-plane. - example: - max_connections: 1000 - additionalProperties: true - restore_config: - $ref: '#/components/schemas/RestoreConfigSpec' - source_node: + description: Unique identifier for the database. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + spec: + $ref: '#/components/schemas/DatabaseSpec2' + tenant_id: type: string - description: The name of the source node to use for sync. This is typically the node (like 'n1') from which the data will be copied to initialize this new node. - example: n1 + description: Unique identifier for the databases's owner. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 example: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 + id: storefront + spec: + database_name: storefront + database_users: + - attributes: + - LOGIN + - SUPERUSER + db_owner: true + password: password + username: admin + nodes: + - host_ids: + - us-east-1 + name: n1 + - host_ids: + - ap-south-1 + name: n2 + - host_ids: + - eu-central-1 + name: n3 + port: 5432 + postgresql_conf: + max_connections: 5000 required: - - name - - host_ids - DatabaseNodeSpec4: + - spec + CreateDatabaseResponse: type: object properties: - backup_config: - $ref: '#/components/schemas/BackupConfigSpec' - cpus: - type: string - description: The number of CPUs to allocate for the database on this node and to use for tuning Postgres. It can include the SI suffix 'm', e.g. '500m' for 500 millicpus. Cannot allocate units smaller than 1m. Defaults to the number of available CPUs on the host if 0 or unspecified. Cannot allocate more CPUs than are available on the host. Whether this limit is enforced depends on the orchestrator. - example: 500m - pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ - host_ids: - type: array - items: - type: string - example: 76f9b8c0-4958-11f0-a489-3bb29577c696 - minLength: 1 - maxLength: 63 - description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. - example: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - minItems: 1 - memory: - type: string - description: The amount of memory in SI or IEC notation to allocate for the database on this node and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. - example: 500M - maxLength: 16 - name: - type: string - description: The name of the database node. - example: n1 - pattern: n[0-9]+ - orchestrator_opts: - $ref: '#/components/schemas/OrchestratorOpts' - port: - type: integer - description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. - example: 5432 - format: int64 - minimum: 0 - maximum: 65535 - postgres_version: - type: string - description: The Postgres version for this node in 'major.minor' format. Overrides the Postgres version set in the DatabaseSpec. - example: "17.6" - pattern: ^\d{2}\.\d{1,2}$ - postgresql_conf: - type: object - description: Additional postgresql.conf settings for this particular node. Will be merged with the settings provided by control-plane. - example: - max_connections: 1000 - additionalProperties: true - restore_config: - $ref: '#/components/schemas/RestoreConfigSpec' - source_node: - type: string - description: The name of the source node to use for sync. This is typically the node (like 'n1') from which the data will be copied to initialize this new node. - example: n1 + database: + $ref: '#/components/schemas/Database' + task: + $ref: '#/components/schemas/Task' example: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 + database: + created_at: "2025-06-18T16:52:05Z" + id: storefront + spec: + database_name: storefront + database_users: + - attributes: + - SUPERUSER + - LOGIN + db_owner: true + username: admin + nodes: + - host_ids: + - us-east-1 + name: n1 + - host_ids: + - ap-south-1 + name: n2 + - host_ids: + - eu-central-1 + name: n3 + port: 5432 + postgres_version: "17.6" + spock_version: "5" + state: creating + updated_at: "2025-06-18T16:52:05Z" + task: + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + status: pending + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create required: - - name - - host_ids - DatabaseSpec: + - task + - database + Database: type: object properties: - backup_config: - $ref: '#/components/schemas/BackupConfigSpec' - cpus: + created_at: type: string - description: The number of CPUs to allocate for the database and to use for tuning Postgres. Defaults to the number of available CPUs on the host. Can include an SI suffix, e.g. '500m' for 500 millicpus. Whether this limit is enforced depends on the orchestrator. - example: 500m - pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ - database_name: + description: The time that the database was created. + example: "2025-01-01T01:30:00Z" + format: date-time + id: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + instances: + $ref: '#/components/schemas/InstanceCollection' + spec: + $ref: '#/components/schemas/DatabaseSpec' + state: + type: string + description: Current state of the database. + example: deleting + enum: + - creating + - modifying + - available + - deleting + - degraded + - failed + - backing_up + - restoring + - unknown + tenant_id: type: string - description: The name of the Postgres database. - example: northwind + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 minLength: 1 - maxLength: 31 - database_users: - type: array - items: - $ref: '#/components/schemas/DatabaseUserSpec' - description: The users to create for this database. - example: + maxLength: 63 + updated_at: + type: string + description: The time that the database was last updated. + example: "2025-01-01T02:30:00Z" + format: date-time + example: + created_at: "2025-01-01T01:30:00Z" + id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + instances: + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + spec: + backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + database_name: northwind + database_users: - attributes: - LOGIN - CREATEDB @@ -5925,18 +4469,107 @@ components: roles: - pgedge_superuser username: admin - maxItems: 16 - memory: - type: string - description: The amount of memory in SI or IEC notation to allocate for the database and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. - example: 500M - maxLength: 16 - nodes: - type: array - items: - $ref: '#/components/schemas/DatabaseNodeSpec' - description: The Spock nodes for this database. - example: + memory: 500M + nodes: + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 - backup_config: repositories: - azure_account: pgedge-backups @@ -6036,201 +4669,198 @@ components: source_database_name: northwind source_node_name: n1 source_node: n1 - minItems: 1 - maxItems: 9 - orchestrator_opts: - $ref: '#/components/schemas/OrchestratorOpts' - port: - type: integer - description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. - example: 5432 - format: int64 - minimum: 0 - maximum: 65535 - postgres_version: - type: string - description: The Postgres version in 'major.minor' format. - example: "17.6" - pattern: ^\d{2}\.\d{1,2}$ - postgresql_conf: - type: object - description: Additional postgresql.conf settings. Will be merged with the settings provided by control-plane. - example: - max_connections: 1000 - maxLength: 64 - additionalProperties: true - restore_config: - $ref: '#/components/schemas/RestoreConfigSpec' - spock_version: - type: string - description: The major version of the Spock extension. - example: "5" - pattern: ^\d{1}$ - example: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - database_name: northwind - database_users: - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - - attributes: - - LOGIN - - CREATEDB - - CREATEROLE - db_owner: false - password: secret - roles: - - pgedge_superuser - username: admin - memory: 500M - nodes: - - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 - source_database_name: northwind - source_node_name: n1 - source_node: n1 - - backup_config: + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + spock_version: "5" + state: backing_up + tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 + updated_at: "2025-01-01T02:30:00Z" + required: + - id + - created_at + - updated_at + - state + DatabaseCollection: + type: array + items: + $ref: '#/components/schemas/Database' + example: + - created_at: "2025-01-01T01:30:00Z" + id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + instances: + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + spec: + backup_config: repositories: - azure_account: pgedge-backups azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 @@ -6263,10 +4893,235 @@ components: id: daily-full-backup type: full cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec + database_name: northwind + database_users: + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin memory: 500M - name: n1 + nodes: + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 orchestrator_opts: swarm: extra_labels: @@ -6328,8 +5183,127 @@ components: source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 source_database_name: northwind source_node_name: n1 - source_node: n1 - - backup_config: + spock_version: "5" + state: creating + tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 + updated_at: "2025-01-01T02:30:00Z" + - created_at: "2025-01-01T01:30:00Z" + id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + instances: + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + - connection_info: + hostname: i-0123456789abcdef.ec2.internal + ipv4_address: 10.24.34.2 + port: 5432 + created_at: "1987-03-24T21:22:02Z" + error: 'failed to get patroni status: connection refused' + host_id: de3b1388-1f0c-42f1-a86c-59ab72f255ec + id: a67cbb36-c3c3-49c9-8aac-f4a0438a883d + node_name: n1 + postgres: + patroni_paused: true + patroni_state: unknown + pending_restart: false + role: primary + version: "18.1" + spock: + read_only: "off" + subscriptions: + - name: sub_n1n2 + provider_node: n2 + status: down + - name: sub_n1n2 + provider_node: n2 + status: down + version: 4.10.0 + state: creating + status_updated_at: "1974-12-13T04:15:04Z" + updated_at: "2006-10-18T16:07:16Z" + spec: + backup_config: repositories: - azure_account: pgedge-backups azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 @@ -6362,10 +5336,235 @@ components: id: daily-full-backup type: full cpus: 500m - host_ids: - - de3b1388-1f0c-42f1-a86c-59ab72f255ec + database_name: northwind + database_users: + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: false + password: secret + roles: + - pgedge_superuser + username: admin memory: 500M - name: n1 + nodes: + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 orchestrator_opts: swarm: extra_labels: @@ -6427,7 +5626,672 @@ components: source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 source_database_name: northwind source_node_name: n1 - source_node: n1 + spock_version: "5" + state: creating + tenant_id: 8210ec10-2dca-406c-ac4a-0661d2189954 + updated_at: "2025-01-01T02:30:00Z" + DatabaseNodeSpec: + type: object + properties: + backup_config: + $ref: '#/components/schemas/BackupConfigSpec' + cpus: + type: string + description: The number of CPUs to allocate for the database on this node and to use for tuning Postgres. It can include the SI suffix 'm', e.g. '500m' for 500 millicpus. Cannot allocate units smaller than 1m. Defaults to the number of available CPUs on the host if 0 or unspecified. Cannot allocate more CPUs than are available on the host. Whether this limit is enforced depends on the orchestrator. + example: 500m + pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ + host_ids: + type: array + items: + type: string + description: A user-specified identifier. Must be 1-63 characters, contain only lower-cased letters and hyphens, start and end with a letter or number, and not contain consecutive hyphens. + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. + example: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + minItems: 1 + memory: + type: string + description: The amount of memory in SI or IEC notation to allocate for the database on this node and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. + example: 500M + maxLength: 16 + name: + type: string + description: The name of the database node. + example: n1 + pattern: n[0-9]+ + orchestrator_opts: + $ref: '#/components/schemas/OrchestratorOpts' + port: + type: integer + description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. + example: 5432 + format: int64 + minimum: 0 + maximum: 65535 + postgres_version: + type: string + description: The Postgres version for this node in 'major.minor' format. Overrides the Postgres version set in the DatabaseSpec. + example: "17.6" + pattern: ^\d{2}\.\d{1,2}$ + postgresql_conf: + type: object + description: Additional postgresql.conf settings for this particular node. Will be merged with the settings provided by control-plane. + example: + max_connections: 1000 + additionalProperties: true + restore_config: + $ref: '#/components/schemas/RestoreConfigSpec' + source_node: + type: string + description: The name of the source node to use for sync. This is typically the node (like 'n1') from which the data will be copied to initialize this new node. + example: n1 + example: + backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + required: + - name + - host_ids + DatabaseNodeSpec2: + type: object + properties: + backup_config: + $ref: '#/components/schemas/BackupConfigSpec' + cpus: + type: string + description: The number of CPUs to allocate for the database on this node and to use for tuning Postgres. It can include the SI suffix 'm', e.g. '500m' for 500 millicpus. Cannot allocate units smaller than 1m. Defaults to the number of available CPUs on the host if 0 or unspecified. Cannot allocate more CPUs than are available on the host. Whether this limit is enforced depends on the orchestrator. + example: 500m + pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ + host_ids: + type: array + items: + type: string + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. + example: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + minItems: 1 + memory: + type: string + description: The amount of memory in SI or IEC notation to allocate for the database on this node and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. + example: 500M + maxLength: 16 + name: + type: string + description: The name of the database node. + example: n1 + pattern: n[0-9]+ + orchestrator_opts: + $ref: '#/components/schemas/OrchestratorOpts' + port: + type: integer + description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. + example: 5432 + format: int64 + minimum: 0 + maximum: 65535 + postgres_version: + type: string + description: The Postgres version for this node in 'major.minor' format. Overrides the Postgres version set in the DatabaseSpec. + example: "17.6" + pattern: ^\d{2}\.\d{1,2}$ + postgresql_conf: + type: object + description: Additional postgresql.conf settings for this particular node. Will be merged with the settings provided by control-plane. + example: + max_connections: 1000 + additionalProperties: true + restore_config: + $ref: '#/components/schemas/RestoreConfigSpec' + source_node: + type: string + description: The name of the source node to use for sync. This is typically the node (like 'n1') from which the data will be copied to initialize this new node. + example: n1 + example: + backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + required: + - name + - host_ids + DatabaseNodeSpec3: + type: object + properties: + backup_config: + $ref: '#/components/schemas/BackupConfigSpec' + cpus: + type: string + description: The number of CPUs to allocate for the database on this node and to use for tuning Postgres. It can include the SI suffix 'm', e.g. '500m' for 500 millicpus. Cannot allocate units smaller than 1m. Defaults to the number of available CPUs on the host if 0 or unspecified. Cannot allocate more CPUs than are available on the host. Whether this limit is enforced depends on the orchestrator. + example: 500m + pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ + host_ids: + type: array + items: + type: string + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. + example: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + minItems: 1 + memory: + type: string + description: The amount of memory in SI or IEC notation to allocate for the database on this node and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. + example: 500M + maxLength: 16 + name: + type: string + description: The name of the database node. + example: n1 + pattern: n[0-9]+ + orchestrator_opts: + $ref: '#/components/schemas/OrchestratorOpts' + port: + type: integer + description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. + example: 5432 + format: int64 + minimum: 0 + maximum: 65535 + postgres_version: + type: string + description: The Postgres version for this node in 'major.minor' format. Overrides the Postgres version set in the DatabaseSpec. + example: "17.6" + pattern: ^\d{2}\.\d{1,2}$ + postgresql_conf: + type: object + description: Additional postgresql.conf settings for this particular node. Will be merged with the settings provided by control-plane. + example: + max_connections: 1000 + additionalProperties: true + restore_config: + $ref: '#/components/schemas/RestoreConfigSpec' + source_node: + type: string + description: The name of the source node to use for sync. This is typically the node (like 'n1') from which the data will be copied to initialize this new node. + example: n1 + example: + backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + required: + - name + - host_ids + DatabaseNodeSpec4: + type: object + properties: + backup_config: + $ref: '#/components/schemas/BackupConfigSpec' + cpus: + type: string + description: The number of CPUs to allocate for the database on this node and to use for tuning Postgres. It can include the SI suffix 'm', e.g. '500m' for 500 millicpus. Cannot allocate units smaller than 1m. Defaults to the number of available CPUs on the host if 0 or unspecified. Cannot allocate more CPUs than are available on the host. Whether this limit is enforced depends on the orchestrator. + example: 500m + pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ + host_ids: + type: array + items: + type: string + example: 76f9b8c0-4958-11f0-a489-3bb29577c696 + minLength: 1 + maxLength: 63 + description: The IDs of the hosts that should run this node. When multiple hosts are specified, one host will chosen as a primary, and the others will be read replicas. + example: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + minItems: 1 + memory: + type: string + description: The amount of memory in SI or IEC notation to allocate for the database on this node and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. + example: 500M + maxLength: 16 + name: + type: string + description: The name of the database node. + example: n1 + pattern: n[0-9]+ + orchestrator_opts: + $ref: '#/components/schemas/OrchestratorOpts' + port: + type: integer + description: The port used by the Postgres database for this node. Overrides the Postgres port set in the DatabaseSpec. + example: 5432 + format: int64 + minimum: 0 + maximum: 65535 + postgres_version: + type: string + description: The Postgres version for this node in 'major.minor' format. Overrides the Postgres version set in the DatabaseSpec. + example: "17.6" + pattern: ^\d{2}\.\d{1,2}$ + postgresql_conf: + type: object + description: Additional postgresql.conf settings for this particular node. Will be merged with the settings provided by control-plane. + example: + max_connections: 1000 + additionalProperties: true + restore_config: + $ref: '#/components/schemas/RestoreConfigSpec' + source_node: + type: string + description: The name of the source node to use for sync. This is typically the node (like 'n1') from which the data will be copied to initialize this new node. + example: n1 + example: + backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 orchestrator_opts: swarm: extra_labels: @@ -6475,7 +6339,7 @@ components: gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: f6b84a99-5e91-4203-be1e-131fe82e5984 + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 s3_endpoint: s3.us-east-1.amazonaws.com s3_key: AKIAIOSFODNN7EXAMPLE @@ -6486,14 +6350,14 @@ components: set: 20250505-153628F target: "123456" type: xid - source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 source_database_name: northwind source_node_name: n1 - spock_version: "5" + source_node: n1 required: - - database_name - - nodes - DatabaseSpec2: + - name + - host_ids + DatabaseSpec: type: object properties: backup_config: @@ -6519,7 +6383,7 @@ components: - LOGIN - CREATEDB - CREATEROLE - db_owner: true + db_owner: false password: secret roles: - pgedge_superuser @@ -6528,7 +6392,7 @@ components: - LOGIN - CREATEDB - CREATEROLE - db_owner: true + db_owner: false password: secret roles: - pgedge_superuser @@ -6537,7 +6401,7 @@ components: - LOGIN - CREATEDB - CREATEROLE - db_owner: true + db_owner: false password: secret roles: - pgedge_superuser @@ -6551,7 +6415,7 @@ components: nodes: type: array items: - $ref: '#/components/schemas/DatabaseNodeSpec2' + $ref: '#/components/schemas/DatabaseNodeSpec' description: The Spock nodes for this database. example: - backup_config: @@ -6567,47 +6431,7 @@ components: gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + id: f6b84a99-5e91-4203-be1e-131fe82e5984 retention_full: 2 retention_full_type: count s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 @@ -6628,7 +6452,7 @@ components: type: full cpus: 500m host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - de3b1388-1f0c-42f1-a86c-59ab72f255ec memory: 500M name: n1 orchestrator_opts: @@ -6678,7 +6502,7 @@ components: gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + id: f6b84a99-5e91-4203-be1e-131fe82e5984 s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 s3_endpoint: s3.us-east-1.amazonaws.com s3_key: AKIAIOSFODNN7EXAMPLE @@ -6689,7 +6513,7 @@ components: set: 20250505-153628F target: "123456" type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 source_database_name: northwind source_node_name: n1 source_node: n1 @@ -6712,60 +6536,20 @@ components: postgresql_conf: type: object description: Additional postgresql.conf settings. Will be merged with the settings provided by control-plane. - example: - max_connections: 1000 - maxLength: 64 - additionalProperties: true - restore_config: - $ref: '#/components/schemas/RestoreConfigSpec' - spock_version: - type: string - description: The major version of the Spock extension. - example: "5" - pattern: ^\d{1}$ - example: - backup_config: - repositories: - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 + example: + max_connections: 1000 + maxLength: 64 + additionalProperties: true + restore_config: + $ref: '#/components/schemas/RestoreConfigSpec' + spock_version: + type: string + description: The major version of the Spock extension. + example: "5" + pattern: ^\d{1}$ + example: + backup_config: + repositories: - azure_account: pgedge-backups azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 azure_endpoint: blob.core.usgovcloudapi.net @@ -6777,7 +6561,7 @@ components: gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + id: f6b84a99-5e91-4203-be1e-131fe82e5984 retention_full: 2 retention_full_type: count s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 @@ -6803,7 +6587,7 @@ components: - LOGIN - CREATEDB - CREATEROLE - db_owner: true + db_owner: false password: secret roles: - pgedge_superuser @@ -6812,7 +6596,7 @@ components: - LOGIN - CREATEDB - CREATEROLE - db_owner: true + db_owner: false password: secret roles: - pgedge_superuser @@ -6821,7 +6605,7 @@ components: - LOGIN - CREATEDB - CREATEROLE - db_owner: true + db_owner: false password: secret roles: - pgedge_superuser @@ -6841,27 +6625,7 @@ components: gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + id: f6b84a99-5e91-4203-be1e-131fe82e5984 retention_full: 2 retention_full_type: count s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 @@ -6870,6 +6634,85 @@ components: s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY s3_region: us-east-1 type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: - azure_account: pgedge-backups azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 azure_endpoint: blob.core.usgovcloudapi.net @@ -6881,7 +6724,7 @@ components: gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + id: f6b84a99-5e91-4203-be1e-131fe82e5984 retention_full: 2 retention_full_type: count s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 @@ -6902,7 +6745,7 @@ components: type: full cpus: 500m host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 + - de3b1388-1f0c-42f1-a86c-59ab72f255ec memory: 500M name: n1 orchestrator_opts: @@ -6952,7 +6795,7 @@ components: gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + id: f6b84a99-5e91-4203-be1e-131fe82e5984 s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 s3_endpoint: s3.us-east-1.amazonaws.com s3_key: AKIAIOSFODNN7EXAMPLE @@ -6963,7 +6806,7 @@ components: set: 20250505-153628F target: "123456" type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 source_database_name: northwind source_node_name: n1 source_node: n1 @@ -6980,7 +6823,7 @@ components: gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + id: f6b84a99-5e91-4203-be1e-131fe82e5984 retention_full: 2 retention_full_type: count s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 @@ -6989,123 +6832,761 @@ components: s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY s3_region: us-east-1 type: s3 - - azure_account: pgedge-backups + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - de3b1388-1f0c-42f1-a86c-59ab72f255ec + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: f6b84a99-5e91-4203-be1e-131fe82e5984 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 02f1a7db-fca8-4521-b57a-2a375c1ced51 + source_database_name: northwind + source_node_name: n1 + spock_version: "5" + required: + - database_name + - nodes + DatabaseSpec2: + type: object + properties: + backup_config: + $ref: '#/components/schemas/BackupConfigSpec' + cpus: + type: string + description: The number of CPUs to allocate for the database and to use for tuning Postgres. Defaults to the number of available CPUs on the host. Can include an SI suffix, e.g. '500m' for 500 millicpus. Whether this limit is enforced depends on the orchestrator. + example: 500m + pattern: ^[0-9]+(\.[0-9]{1,3}|m)?$ + database_name: + type: string + description: The name of the Postgres database. + example: northwind + minLength: 1 + maxLength: 31 + database_users: + type: array + items: + $ref: '#/components/schemas/DatabaseUserSpec' + description: The users to create for this database. + example: + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + maxItems: 16 + memory: + type: string + description: The amount of memory in SI or IEC notation to allocate for the database and to use for tuning Postgres. Defaults to the total available memory on the host. Whether this limit is enforced depends on the orchestrator. + example: 500M + maxLength: 16 + nodes: + type: array + items: + $ref: '#/components/schemas/DatabaseNodeSpec2' + description: The Spock nodes for this database. + example: + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 azure_endpoint: blob.core.usgovcloudapi.net azure_key: YXpLZXk= base_path: /backups custom_options: s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 s3_endpoint: s3.us-east-1.amazonaws.com s3_key: AKIAIOSFODNN7EXAMPLE s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY s3_region: us-east-1 type: s3 - - azure_account: pgedge-backups + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 azure_endpoint: blob.core.usgovcloudapi.net azure_key: YXpLZXk= base_path: /backups custom_options: s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - storage-upload-chunk-size: 5MiB gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 gcs_endpoint: localhost gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - retention_full: 2 - retention_full_type: count s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 s3_endpoint: s3.us-east-1.amazonaws.com s3_key: AKIAIOSFODNN7EXAMPLE s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY s3_region: us-east-1 type: s3 - schedules: - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - - cron_expression: 0 6 * * ? - id: daily-full-backup - type: full - cpus: 500m - host_ids: - - 76f9b8c0-4958-11f0-a489-3bb29577c696 - memory: 500M - name: n1 - orchestrator_opts: - swarm: - extra_labels: - traefik.enable: "true" - traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) - extra_networks: - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - - aliases: - - pg-db - - db-alias - driver_opts: - com.docker.network.endpoint.expose: "true" - id: traefik-public - extra_volumes: - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - - destination_path: /backups/container - host_path: /Users/user/backups/host - port: 5432 - postgres_version: "17.6" - postgresql_conf: - max_connections: 1000 - restore_config: - repository: - azure_account: pgedge-backups - azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - azure_endpoint: blob.core.usgovcloudapi.net - azure_key: YXpLZXk= - base_path: /backups - custom_options: - s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab - gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - gcs_endpoint: localhost - gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== - id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 - s3_endpoint: s3.us-east-1.amazonaws.com - s3_key: AKIAIOSFODNN7EXAMPLE - s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - s3_region: us-east-1 - type: s3 - restore_options: - set: 20250505-153628F - target: "123456" - type: xid - source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 - source_database_name: northwind - source_node_name: n1 - source_node: n1 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + - backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + host_ids: + - 76f9b8c0-4958-11f0-a489-3bb29577c696 + memory: 500M + name: n1 + orchestrator_opts: + swarm: + extra_labels: + traefik.enable: "true" + traefik.tcp.routers.mydb.rule: HostSNI(`mydb.example.com`) + extra_networks: + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + - aliases: + - pg-db + - db-alias + driver_opts: + com.docker.network.endpoint.expose: "true" + id: traefik-public + extra_volumes: + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + - destination_path: /backups/container + host_path: /Users/user/backups/host + port: 5432 + postgres_version: "17.6" + postgresql_conf: + max_connections: 1000 + restore_config: + repository: + azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + restore_options: + set: 20250505-153628F + target: "123456" + type: xid + source_database_id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + source_database_name: northwind + source_node_name: n1 + source_node: n1 + minItems: 1 + maxItems: 9 + orchestrator_opts: + $ref: '#/components/schemas/OrchestratorOpts' + port: + type: integer + description: The port used by the Postgres database. If the port is 0, each instance will be assigned a random port. If the port is unspecified, the database will not be exposed on any port, dependent on orchestrator support for that feature. + example: 5432 + format: int64 + minimum: 0 + maximum: 65535 + postgres_version: + type: string + description: The Postgres version in 'major.minor' format. + example: "17.6" + pattern: ^\d{2}\.\d{1,2}$ + postgresql_conf: + type: object + description: Additional postgresql.conf settings. Will be merged with the settings provided by control-plane. + example: + max_connections: 1000 + maxLength: 64 + additionalProperties: true + restore_config: + $ref: '#/components/schemas/RestoreConfigSpec' + spock_version: + type: string + description: The major version of the Spock extension. + example: "5" + pattern: ^\d{1}$ + example: + backup_config: + repositories: + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + - azure_account: pgedge-backups + azure_container: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + azure_endpoint: blob.core.usgovcloudapi.net + azure_key: YXpLZXk= + base_path: /backups + custom_options: + s3-kms-key-id: 1234abcd-12ab-34cd-56ef-1234567890ab + storage-upload-chunk-size: 5MiB + gcs_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + gcs_endpoint: localhost + gcs_key: ZXhhbXBsZSBnY3Mga2V5Cg== + id: 76f9b8c0-4958-11f0-a489-3bb29577c696 + retention_full: 2 + retention_full_type: count + s3_bucket: pgedge-backups-9f81786f-373b-4ff2-afee-e054a06a96f1 + s3_endpoint: s3.us-east-1.amazonaws.com + s3_key: AKIAIOSFODNN7EXAMPLE + s3_key_secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + s3_region: us-east-1 + type: s3 + schedules: + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + - cron_expression: 0 6 * * ? + id: daily-full-backup + type: full + cpus: 500m + database_name: northwind + database_users: + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + - attributes: + - LOGIN + - CREATEDB + - CREATEROLE + db_owner: true + password: secret + roles: + - pgedge_superuser + username: admin + memory: 500M + nodes: - backup_config: repositories: - azure_account: pgedge-backups @@ -9382,7 +9863,7 @@ components: created_at: type: string description: The time that the instance was created. - example: "1984-01-30T10:40:13Z" + example: "2006-12-23T09:53:03Z" format: date-time error: type: string @@ -9424,7 +9905,7 @@ components: updated_at: type: string description: The time that the instance was last modified. - example: "1996-05-27T17:04:41Z" + example: "2012-08-16T06:20:51Z" format: date-time description: An instance of pgEdge Postgres running on a host. (default view) example: @@ -9652,6 +10133,40 @@ components: status: completed task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 type: create + ListHostTasksResponse: + type: object + properties: + tasks: + type: array + items: + $ref: '#/components/schemas/Task' + example: + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + example: + tasks: + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + entity_id: host-1 + host_id: host-1 + scope: host + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: remove_host ListHostsResponse: type: object properties: @@ -9851,6 +10366,65 @@ components: spock_version: "5" required: - hosts + ListTasksResponse: + type: object + properties: + tasks: + type: array + items: + $ref: '#/components/schemas/Task' + example: + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + - completed_at: "2025-06-18T16:52:35Z" + created_at: "2025-06-18T16:52:05Z" + database_id: storefront + entity_id: storefront + scope: database + status: completed + task_id: 019783f4-75f4-71e7-85a3-c9b96b345d77 + type: create + example: + tasks: + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + database_id: storefront + entity_id: storefront + instance_id: storefront-n1-689qacsi + scope: database + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: node_backup + - completed_at: "2025-06-18T17:54:36Z" + created_at: "2025-06-18T17:54:28Z" + entity_id: host-1 + host_id: host-1 + scope: host + status: completed + task_id: 0197842d-9082-7496-b787-77bd2e11809f + type: remove_host Listdatabasesresponse: type: object properties: diff --git a/changes/unreleased/Added-20260114-162946.yaml b/changes/unreleased/Added-20260114-162946.yaml new file mode 100644 index 00000000..49d246f8 --- /dev/null +++ b/changes/unreleased/Added-20260114-162946.yaml @@ -0,0 +1,3 @@ +kind: Added +body: Added new API endpoints to interact with host-scoped tasks as well as an endpoint to list tasks across all scopes. +time: 2026-01-14T16:29:46.619212-05:00 diff --git a/client/interface.go b/client/interface.go index c285b988..6cbdb834 100644 --- a/client/interface.go +++ b/client/interface.go @@ -22,9 +22,13 @@ type Client interface { UpdateDatabase(ctx context.Context, req *api.UpdateDatabasePayload) (*api.UpdateDatabaseResponse, error) DeleteDatabase(ctx context.Context, req *api.DeleteDatabasePayload) (*api.DeleteDatabaseResponse, error) BackupDatabaseNode(ctx context.Context, req *api.BackupDatabaseNodePayload) (*api.BackupDatabaseNodeResponse, error) + ListTasks(ctx context.Context, req *api.ListTasksPayload) (*api.ListTasksResponse, error) ListDatabaseTasks(ctx context.Context, req *api.ListDatabaseTasksPayload) (*api.ListDatabaseTasksResponse, error) GetDatabaseTask(ctx context.Context, req *api.GetDatabaseTaskPayload) (*api.Task, error) GetDatabaseTaskLog(ctx context.Context, req *api.GetDatabaseTaskLogPayload) (*api.TaskLog, error) + ListHostTasks(ctx context.Context, req *api.ListHostTasksPayload) (*api.ListHostTasksResponse, error) + GetHostTask(ctx context.Context, req *api.GetHostTaskPayload) (*api.Task, error) + GetHostTaskLog(ctx context.Context, req *api.GetHostTaskLogPayload) (*api.TaskLog, error) RestoreDatabase(ctx context.Context, req *api.RestoreDatabasePayload) (*api.RestoreDatabaseResponse, error) GetVersion(ctx context.Context) (*api.VersionInfo, error) RestartInstance(ctx context.Context, req *api.RestartInstancePayload) (*api.RestartInstanceResponse, error) @@ -33,6 +37,8 @@ type Client interface { FailoverDatabaseNode(ctx context.Context, req *api.FailoverDatabaseNodeRequest) (*api.FailoverDatabaseNodeResponse, error) // Helper methods - WaitForTask(ctx context.Context, req *api.GetDatabaseTaskPayload) (*api.Task, error) - FollowTask(ctx context.Context, req *api.GetDatabaseTaskLogPayload, handler func(e *api.TaskLogEntry)) error + WaitForDatabaseTask(ctx context.Context, req *api.GetDatabaseTaskPayload) (*api.Task, error) + WaitForHostTask(ctx context.Context, req *api.GetHostTaskPayload) (*api.Task, error) + FollowDatabaseTask(ctx context.Context, req *api.GetDatabaseTaskLogPayload, handler func(e *api.TaskLogEntry)) error + FollowHostTask(ctx context.Context, req *api.GetHostTaskLogPayload, handler func(e *api.TaskLogEntry)) error } diff --git a/client/multi.go b/client/multi.go index 67e88534..bb8209ca 100644 --- a/client/multi.go +++ b/client/multi.go @@ -207,6 +207,14 @@ func (c *MultiServerClient) BackupDatabaseNode(ctx context.Context, req *api.Bac return server.BackupDatabaseNode(ctx, req) } +func (c *MultiServerClient) ListTasks(ctx context.Context, req *api.ListTasksPayload) (res *api.ListTasksResponse, err error) { + server, err := c.liveServer(ctx) + if err != nil { + return nil, err + } + return server.ListTasks(ctx, req) +} + func (c *MultiServerClient) ListDatabaseTasks(ctx context.Context, req *api.ListDatabaseTasksPayload) (res *api.ListDatabaseTasksResponse, err error) { server, err := c.liveServer(ctx) if err != nil { @@ -231,6 +239,30 @@ func (c *MultiServerClient) GetDatabaseTaskLog(ctx context.Context, req *api.Get return server.GetDatabaseTaskLog(ctx, req) } +func (c *MultiServerClient) ListHostTasks(ctx context.Context, req *api.ListHostTasksPayload) (*api.ListHostTasksResponse, error) { + server, err := c.liveServer(ctx) + if err != nil { + return nil, err + } + return server.ListHostTasks(ctx, req) +} + +func (c *MultiServerClient) GetHostTask(ctx context.Context, req *api.GetHostTaskPayload) (*api.Task, error) { + server, err := c.liveServer(ctx) + if err != nil { + return nil, err + } + return server.GetHostTask(ctx, req) +} + +func (c *MultiServerClient) GetHostTaskLog(ctx context.Context, req *api.GetHostTaskLogPayload) (*api.TaskLog, error) { + server, err := c.liveServer(ctx) + if err != nil { + return nil, err + } + return server.GetHostTaskLog(ctx, req) +} + func (c *MultiServerClient) RestoreDatabase(ctx context.Context, req *api.RestoreDatabasePayload) (res *api.RestoreDatabaseResponse, err error) { server, err := c.liveServer(ctx) if err != nil { @@ -278,20 +310,36 @@ func (c *MultiServerClient) FailoverDatabaseNode(ctx context.Context, req *api.F return server.FailoverDatabaseNode(ctx, req) } -func (c *MultiServerClient) WaitForTask(ctx context.Context, req *api.GetDatabaseTaskPayload) (*api.Task, error) { +func (c *MultiServerClient) WaitForDatabaseTask(ctx context.Context, req *api.GetDatabaseTaskPayload) (*api.Task, error) { + server, err := c.liveServer(ctx) + if err != nil { + return nil, err + } + return server.WaitForDatabaseTask(ctx, req) +} + +func (c *MultiServerClient) WaitForHostTask(ctx context.Context, req *api.GetHostTaskPayload) (*api.Task, error) { server, err := c.liveServer(ctx) if err != nil { return nil, err } - return server.WaitForTask(ctx, req) + return server.WaitForHostTask(ctx, req) +} + +func (c *MultiServerClient) FollowDatabaseTask(ctx context.Context, req *api.GetDatabaseTaskLogPayload, handler func(e *api.TaskLogEntry)) error { + server, err := c.liveServer(ctx) + if err != nil { + return err + } + return server.FollowDatabaseTask(ctx, req, handler) } -func (c *MultiServerClient) FollowTask(ctx context.Context, req *api.GetDatabaseTaskLogPayload, handler func(e *api.TaskLogEntry)) error { +func (c *MultiServerClient) FollowHostTask(ctx context.Context, req *api.GetHostTaskLogPayload, handler func(e *api.TaskLogEntry)) error { server, err := c.liveServer(ctx) if err != nil { return err } - return server.FollowTask(ctx, req, handler) + return server.FollowHostTask(ctx, req, handler) } func (c *MultiServerClient) liveServer(ctx context.Context) (*SingleServerClient, error) { diff --git a/client/single.go b/client/single.go index 45a2b18d..3b886095 100644 --- a/client/single.go +++ b/client/single.go @@ -15,6 +15,12 @@ var ErrInvalidServerConfig = errors.New("server configuration is empty") const taskPollInterval = 500 * time.Millisecond +var taskEnded = map[string]bool{ + TaskStatusCompleted: true, + TaskStatusCanceled: true, + TaskStatusFailed: true, +} + type SingleServerClient struct { api *api.Client } @@ -63,6 +69,10 @@ func NewSingleServerClient(server ServerConfig) (*SingleServerClient, error) { CancelDatabaseTaskEndpoint: cli.CancelDatabaseTask(), SwitchoverDatabaseNodeEndpoint: cli.SwitchoverDatabaseNode(), FailoverDatabaseNodeEndpoint: cli.FailoverDatabaseNode(), + ListHostTasksEndpoint: cli.ListHostTasks(), + GetHostTaskEndpoint: cli.GetHostTask(), + GetHostTaskLogEndpoint: cli.GetHostTaskLog(), + ListTasksEndpoint: cli.ListTasks(), }, }, nil } @@ -132,6 +142,11 @@ func (c *SingleServerClient) BackupDatabaseNode(ctx context.Context, req *api.Ba return resp, translateErr(err) } +func (c *SingleServerClient) ListTasks(ctx context.Context, req *api.ListTasksPayload) (*api.ListTasksResponse, error) { + resp, err := c.api.ListTasks(ctx, req) + return resp, translateErr(err) +} + func (c *SingleServerClient) ListDatabaseTasks(ctx context.Context, req *api.ListDatabaseTasksPayload) (*api.ListDatabaseTasksResponse, error) { resp, err := c.api.ListDatabaseTasks(ctx, req) return resp, translateErr(err) @@ -147,6 +162,21 @@ func (c *SingleServerClient) GetDatabaseTaskLog(ctx context.Context, req *api.Ge return resp, translateErr(err) } +func (c *SingleServerClient) ListHostTasks(ctx context.Context, req *api.ListHostTasksPayload) (*api.ListHostTasksResponse, error) { + resp, err := c.api.ListHostTasks(ctx, req) + return resp, translateErr(err) +} + +func (c *SingleServerClient) GetHostTask(ctx context.Context, req *api.GetHostTaskPayload) (*api.Task, error) { + resp, err := c.api.GetHostTask(ctx, req) + return resp, translateErr(err) +} + +func (c *SingleServerClient) GetHostTaskLog(ctx context.Context, req *api.GetHostTaskLogPayload) (*api.TaskLog, error) { + resp, err := c.api.GetHostTaskLog(ctx, req) + return resp, translateErr(err) +} + func (c *SingleServerClient) RestoreDatabase(ctx context.Context, req *api.RestoreDatabasePayload) (*api.RestoreDatabaseResponse, error) { resp, err := c.api.RestoreDatabase(ctx, req) return resp, translateErr(err) @@ -162,21 +192,33 @@ func (c *SingleServerClient) RestartInstance(ctx context.Context, req *api.Resta return resp, translateErr(err) } -func (c *SingleServerClient) WaitForTask(ctx context.Context, req *api.GetDatabaseTaskPayload) (*api.Task, error) { +func (c *SingleServerClient) WaitForDatabaseTask(ctx context.Context, req *api.GetDatabaseTaskPayload) (*api.Task, error) { + return c.waitForTask(ctx, func(ctx context.Context) (*api.Task, error) { + return c.GetDatabaseTask(ctx, req) + }) +} + +func (c *SingleServerClient) WaitForHostTask(ctx context.Context, req *api.GetHostTaskPayload) (*api.Task, error) { + return c.waitForTask(ctx, func(ctx context.Context) (*api.Task, error) { + return c.GetHostTask(ctx, req) + }) +} + +func (c *SingleServerClient) waitForTask(ctx context.Context, getTask func(context.Context) (*api.Task, error)) (*api.Task, error) { ticker := time.NewTicker(taskPollInterval) defer ticker.Stop() - task, err := c.GetDatabaseTask(ctx, req) + task, err := getTask(ctx) if err != nil { return nil, err } - for task.Status != TaskStatusCompleted && task.Status != TaskStatusCanceled && task.Status != TaskStatusFailed { + for !taskEnded[task.Status] { select { case <-ctx.Done(): return nil, ctx.Err() case <-ticker.C: - task, err = c.GetDatabaseTask(ctx, req) + task, err = getTask(ctx) if err != nil { return nil, err } @@ -185,6 +227,7 @@ func (c *SingleServerClient) WaitForTask(ctx context.Context, req *api.GetDataba return task, nil } + func (c *SingleServerClient) CancelDatabaseTask(ctx context.Context, req *api.CancelDatabaseTaskPayload) (*api.Task, error) { resp, err := c.api.CancelDatabaseTask(ctx, req) return resp, translateErr(err) @@ -200,7 +243,7 @@ func (c *SingleServerClient) FailoverDatabaseNode(ctx context.Context, req *api. return resp, translateErr(err) } -func (c *SingleServerClient) FollowTask(ctx context.Context, req *api.GetDatabaseTaskLogPayload, handler func(e *api.TaskLogEntry)) error { +func (c *SingleServerClient) FollowDatabaseTask(ctx context.Context, req *api.GetDatabaseTaskLogPayload, handler func(e *api.TaskLogEntry)) error { ticker := time.NewTicker(taskPollInterval) defer ticker.Stop() @@ -219,7 +262,7 @@ func (c *SingleServerClient) FollowTask(ctx context.Context, req *api.GetDatabas handler(entry) } - for taskLog.TaskStatus != TaskStatusCompleted && taskLog.TaskStatus != TaskStatusCanceled && taskLog.TaskStatus != TaskStatusFailed { + for !taskEnded[taskLog.TaskStatus] { select { case <-ctx.Done(): return ctx.Err() @@ -238,3 +281,42 @@ func (c *SingleServerClient) FollowTask(ctx context.Context, req *api.GetDatabas return nil } + +func (c *SingleServerClient) FollowHostTask(ctx context.Context, req *api.GetHostTaskLogPayload, handler func(e *api.TaskLogEntry)) error { + ticker := time.NewTicker(taskPollInterval) + defer ticker.Stop() + + curr := &api.GetHostTaskLogPayload{ + HostID: req.HostID, + TaskID: req.TaskID, + AfterEntryID: req.AfterEntryID, + Limit: req.Limit, + } + + taskLog, err := c.GetHostTaskLog(ctx, curr) + if err != nil { + return err + } + for _, entry := range taskLog.Entries { + handler(entry) + } + + for !taskEnded[taskLog.TaskStatus] { + select { + case <-ctx.Done(): + return ctx.Err() + case <-ticker.C: + curr.AfterEntryID = taskLog.LastEntryID + + taskLog, err = c.GetHostTaskLog(ctx, curr) + if err != nil { + return err + } + for _, entry := range taskLog.Entries { + handler(entry) + } + } + } + + return nil +} diff --git a/docs/using/tasks-logs.md b/docs/using/tasks-logs.md index 3f297fbd..279f76b8 100644 --- a/docs/using/tasks-logs.md +++ b/docs/using/tasks-logs.md @@ -4,11 +4,49 @@ The pgEdge Control Plane provides tools to monitor asynchronous operations and a ## Tasks -Every asynchronous database operation managed by the pgEdge Control Plane produces a *task* that you can use to track the progress of that operation. +Every asynchronous operation managed by the pgEdge Control Plane produces a *task* that you can use to track the progress of that operation. Tasks are scoped to either a database or a host, depending on the type of operation. -### Listing Tasks +### Listing All Tasks -To list tasks for a database, submit a `GET` request to the +To list all tasks across all scopes, submit a `GET` request to the `/v1/tasks` endpoint: + +=== "curl" + + ```sh + curl http://host-3:3000/v1/tasks + ``` + +You can filter tasks by scope (`database` or `host`) and entity ID: + +=== "curl" + + ```sh + # List only database tasks + curl 'http://host-3:3000/v1/tasks?scope=database' + + # List tasks for a specific database + curl 'http://host-3:3000/v1/tasks?scope=database&entity_id=example' + + # List only host tasks + curl 'http://host-3:3000/v1/tasks?scope=host' + + # List tasks for a specific host + curl 'http://host-3:3000/v1/tasks?scope=host&entity_id=host-1' + ``` + +This endpoint also supports pagination and sorting: + +=== "curl" + + ```sh + curl 'http://host-3:3000/v1/tasks?limit=10&after_task_id=404ecbe0-5cda-11f0-900b-a74a79e3bdba&sort_order=asc' + ``` + +## Database Tasks + +### Listing Database Tasks + +To list tasks for a specific database, submit a `GET` request to the `/v1/databases/{database_id}/tasks` endpoint. For example: === "curl" @@ -68,6 +106,58 @@ You can also limit your request to only the most recent log entries with the curl 'http://host-3:3000/v1/databases/example/tasks/d3cd2fab-4b1f-4eb9-b614-181c10b07acd/log?limit=10' ``` +## Host Tasks + +Some operations, such as removing a host from the cluster, produce tasks scoped to a host rather than a database. + +### Listing Host Tasks + +To list tasks for a specific host, submit a `GET` request to the +`/v1/hosts/{host_id}/tasks` endpoint: + +=== "curl" + + ```sh + curl http://host-3:3000/v1/hosts/host-1/tasks + ``` + +This endpoint supports the same pagination and sorting options as the database tasks endpoint: + +=== "curl" + + ```sh + curl 'http://host-3:3000/v1/hosts/host-1/tasks?limit=5&after_task_id=404ecbe0-5cda-11f0-900b-a74a79e3bdba&sort_order=asc' + ``` + +### Getting a Specific Host Task + +To fetch details for a specific host task, submit a `GET` request to the `/v1/hosts/{host_id}/tasks/{task_id}` endpoint: + +=== "curl" + + ```sh + curl http://host-3:3000/v1/hosts/host-1/tasks/d3cd2fab-4b1f-4eb9-b614-181c10b07acd + ``` + +### Getting Host Task Logs + +You can fetch log messages for a host task by submitting a `GET` request to the +`/v1/hosts/{host_id}/tasks/{task_id}/logs` endpoint: + +=== "curl" + + ```sh + curl http://host-3:3000/v1/hosts/host-1/tasks/d3cd2fab-4b1f-4eb9-b614-181c10b07acd/logs + ``` + +The same pagination options (`after_entry_id` and `limit`) are supported: + +=== "curl" + + ```sh + curl 'http://host-3:3000/v1/hosts/host-1/tasks/d3cd2fab-4b1f-4eb9-b614-181c10b07acd/logs?limit=10' + ``` + ## Viewing Postgres Logs By default, each database is configured to write log files to the following directory: diff --git a/e2e/cancel_task_test.go b/e2e/cancel_task_test.go index aedbfed2..ff713bd9 100644 --- a/e2e/cancel_task_test.go +++ b/e2e/cancel_task_test.go @@ -61,7 +61,7 @@ func testCancelDB(t *testing.T) { } t.Logf("canceled") - final_task, err := fixture.Client.WaitForTask(t.Context(), &controlplane.GetDatabaseTaskPayload{ + final_task, err := fixture.Client.WaitForDatabaseTask(t.Context(), &controlplane.GetDatabaseTaskPayload{ DatabaseID: database.ID, TaskID: cancelation_task.TaskID, }) diff --git a/e2e/database_test.go b/e2e/database_test.go index 8416bd7d..5612ba40 100644 --- a/e2e/database_test.go +++ b/e2e/database_test.go @@ -337,7 +337,7 @@ func (d *DatabaseFixture) GetInstances(matcher InstanceMatcher) iter.Seq[*contro } func (d *DatabaseFixture) waitForTask(ctx context.Context, task *controlplane.Task) error { - task, err := d.client.WaitForTask(ctx, &controlplane.GetDatabaseTaskPayload{ + task, err := d.client.WaitForDatabaseTask(ctx, &controlplane.GetDatabaseTaskPayload{ DatabaseID: d.ID, TaskID: task.TaskID, }) diff --git a/hack/dev-env.zsh b/hack/dev-env.zsh index ce26fd27..edd9a023 100644 --- a/hack/dev-env.zsh +++ b/hack/dev-env.zsh @@ -69,6 +69,33 @@ _use-test-config() { done } +_choose-scope() { + # (j:\n:) joins the array with newlines + local scope_choice=$(echo "host\ndatabase" | sk) + + if [[ -z "${scope_choice}" ]]; then + return 1 + fi + + local scope=$(jq -r '.id' <<<"${scope_choice}") + echo "using scope ${scope}" >&2 + echo "${scope_choice}" +} + +_choose-host() { + local host_choice=$(restish host-1 list-hosts \ + | jq -c '.hosts[]? | { id, state: .status.state, hostname, ipv4_address }' \ + | sk --preview 'echo {} | jq') + + if [[ -z "${host_choice}" ]]; then + return 1 + fi + + local host_id=$(jq -r '.id' <<<"${host_choice}") + echo "using database ${host_id}" >&2 + echo "${host_choice}" +} + _choose-database() { local database_choice=$(restish host-1 list-databases \ | jq -c '.databases[]? | { id, state, created_at, updated_at }' \ @@ -112,7 +139,11 @@ _choose-user() { } _choose-task() { - local task_choice=$(restish host-1 list-database-tasks $1 \ + local scope="$1" + local entity_id="$2" + local task_choice=$(restish host-1 list-tasks \ + --scope "${scope}" \ + --entity-id "${entity_id}" \ | jq -c '.tasks[]?' \ | sk --preview 'echo {} | jq') @@ -486,12 +517,14 @@ EOF } cp-follow-task() { - local o_database_id + local o_scope + local o_entity_id local o_task_id local o_help zparseopts -D -F -K -- \ - {d,-database-id}:=o_database_id \ + {s,-scope}:=o_scope \ + {e,-entity-id}:=o_entity_id \ {t,-task-id}:=o_task_id \ {h,-help}=o_help || return @@ -500,7 +533,8 @@ cp-follow-task() { return fi - local database_id="${o_database_id[-1]}" + local scope="${o_scope[-1]}" + local entity_id="${o_entity_id[-1]}" local task_id="${o_task_id[-1]}" # If we have an api response on stdin, we'll try to extract the database ID @@ -511,27 +545,36 @@ cp-follow-task() { # echo the input for visibility echo "${input}" - database_id=$(<<<"${input}" jq -r '.task.database_id') + scope=$(<<<"${input}" jq -r '.task.scope') + entity_id=$(<<<"${input}" jq -r '.task.entity_id') task_id=$(<<<"${input}" jq -r '.task.task_id') - if [[ -z "${database_id}" || -z "${task_id}" ]]; then + if [[ -z "${scope}" || -z "${entity_id}" || -z "${task_id}" ]]; then echo "no task object found on stdin" >&2 return 1 fi fi - if [[ -z "${database_id}" ]]; then - local database=$(_choose-database) + if [[ -z "${scope}" ]]; then + local scope=$(_choose-scope) + + if [[ -z "${scope}" ]]; then + return 1 + fi + fi + + if [[ -z "${entity_id}" ]]; then + local entity=$(_choose-${scope}) - if [[ -z "${database}" ]]; then + if [[ -z "${entity}" ]]; then return 1 fi - database_id=$(<<<"${database}" jq -r '.id') + entity_id=$(<<<"${entity}" jq -r '.id') fi if [[ -z "${task_id}" ]]; then - local task=$(_choose-task "${database_id}") + local task=$(_choose-task "${scope}" "${entity_id}") if [[ -z "${task}" ]]; then return 1 @@ -548,8 +591,8 @@ cp-follow-task() { while :; do # Get next set of entries resp=$(restish host-1 \ - get-database-task-log \ - ${database_id} \ + get-${scope}-task-log \ + ${entity_id} \ ${task_id} \ --after-entry-id "${last_entry_id}") @@ -564,15 +607,15 @@ cp-follow-task() { last_entry_id=${next_last_entry_id} fi - sleep 1s - [[ "${task_status}" != "completed" && \ "${task_status}" != "failed" && \ "${task_status}" != "canceled" ]] || break + + sleep 1s done echo - echo "database ${database_id} task ${task_id} ${task_status}" + echo "${scope} entity ${entity_id} task ${task_id} ${task_status}" } ######### diff --git a/server/internal/api/apiv1/convert.go b/server/internal/api/apiv1/convert.go index ddf77acf..944ff76f 100644 --- a/server/internal/api/apiv1/convert.go +++ b/server/internal/api/apiv1/convert.go @@ -791,3 +791,77 @@ func extraNetworksToAPI(nets []database.ExtraNetworkSpec) []*api.ExtraNetworkSpe } return result } + +func taskListOptionsFromHost(req *api.ListHostTasksPayload) (task.TaskListOptions, error) { + options := task.TaskListOptions{} + if req.Limit != nil { + options.Limit = *req.Limit + } + if req.AfterTaskID != nil { + afterTaskID, err := uuid.Parse(*req.AfterTaskID) + if err != nil { + return task.TaskListOptions{}, fmt.Errorf("invalid after task ID %q: %w", *req.AfterTaskID, err) + } + options.AfterTaskID = afterTaskID + } + if req.SortOrder != nil { + switch *req.SortOrder { + case "asc", "ascend", "ascending": + options.SortOrder = task.SortAscend + case "desc", "descend", "descending": + options.SortOrder = task.SortDescend + default: + return task.TaskListOptions{}, fmt.Errorf("invalid sort order %q", *req.SortOrder) + } + } + return options, nil +} + +func taskLogOptionsFromHost(req *api.GetHostTaskLogPayload) (task.TaskLogOptions, error) { + options := task.TaskLogOptions{} + if req.Limit != nil { + options.Limit = *req.Limit + } + if req.AfterEntryID != nil { + afterEntryID, err := uuid.Parse(*req.AfterEntryID) + if err != nil { + return task.TaskLogOptions{}, fmt.Errorf("invalid after entry ID %q: %w", *req.AfterEntryID, err) + } + options.AfterEntryID = afterEntryID + } + return options, nil +} + +func taskListOptionsFromGeneric(req *api.ListTasksPayload) (task.Scope, string, error) { + if req.Scope == nil { + // No scope specified - return empty scope and entity ID + return "", "", nil + } + + scope, err := parseScope(*req.Scope) + if err != nil { + return "", "", err + } + + var entityID string + if req.EntityID != nil { + id, err := identToString(*req.EntityID, []string{"entity_id"}) + if err != nil { + return "", "", err + } + entityID = id + } + + return scope, entityID, nil +} + +func parseScope(scopeStr string) (task.Scope, error) { + switch scopeStr { + case "database": + return task.ScopeDatabase, nil + case "host": + return task.ScopeHost, nil + default: + return "", fmt.Errorf("invalid scope %q", scopeStr) + } +} diff --git a/server/internal/api/apiv1/post_init_handlers.go b/server/internal/api/apiv1/post_init_handlers.go index a6a40f68..abf4da35 100644 --- a/server/internal/api/apiv1/post_init_handlers.go +++ b/server/internal/api/apiv1/post_init_handlers.go @@ -1083,3 +1083,113 @@ func hasPrimaryInstance(instances []*database.Instance) bool { } return false } + +func (s *PostInitHandlers) ListHostTasks(ctx context.Context, req *api.ListHostTasksPayload) (*api.ListHostTasksResponse, error) { + hostID, err := hostIdentToString(req.HostID) + if err != nil { + return nil, err + } + + options, err := taskListOptionsFromHost(req) + if err != nil { + return nil, makeInvalidInputErr(err) + } + + tasks, err := s.taskSvc.GetTasks(ctx, task.ScopeHost, hostID, options) + if err != nil { + return nil, apiErr(err) + } + + return &api.ListHostTasksResponse{ + Tasks: tasksToAPI(tasks), + }, nil +} + +func (s *PostInitHandlers) GetHostTask(ctx context.Context, req *api.GetHostTaskPayload) (*api.Task, error) { + hostID, err := hostIdentToString(req.HostID) + if err != nil { + return nil, err + } + taskID, err := uuid.Parse(req.TaskID) + if err != nil { + return nil, ErrInvalidTaskID + } + + t, err := s.taskSvc.GetTask(ctx, task.ScopeHost, hostID, taskID) + if err != nil { + return nil, apiErr(err) + } + + return taskToAPI(t), nil +} + +func (s *PostInitHandlers) GetHostTaskLog(ctx context.Context, req *api.GetHostTaskLogPayload) (*api.TaskLog, error) { + hostID, err := hostIdentToString(req.HostID) + if err != nil { + return nil, err + } + taskID, err := uuid.Parse(req.TaskID) + if err != nil { + return nil, ErrInvalidTaskID + } + + t, err := s.taskSvc.GetTask(ctx, task.ScopeHost, hostID, taskID) + if err != nil { + return nil, apiErr(err) + } + + options, err := taskLogOptionsFromHost(req) + if err != nil { + return nil, makeInvalidInputErr(err) + } + + log, err := s.taskSvc.GetTaskLog(ctx, task.ScopeHost, hostID, taskID, options) + if err != nil { + return nil, apiErr(err) + } + + return taskLogToAPI(log, t.Status), nil +} + +func (s *PostInitHandlers) ListTasks(ctx context.Context, req *api.ListTasksPayload) (*api.ListTasksResponse, error) { + // Validation: entity_id requires scope + if req.EntityID != nil && req.Scope == nil { + return nil, makeInvalidInputErr(errors.New("entity_id requires scope to be set")) + } + + scope, entityID, err := taskListOptionsFromGeneric(req) + if err != nil { + return nil, makeInvalidInputErr(err) + } + + options := task.TaskListOptions{} + if req.Limit != nil { + options.Limit = *req.Limit + } + if req.AfterTaskID != nil { + afterTaskID, err := uuid.Parse(*req.AfterTaskID) + if err != nil { + return nil, makeInvalidInputErr(fmt.Errorf("invalid after task ID %q: %w", *req.AfterTaskID, err)) + } + options.AfterTaskID = afterTaskID + } + if req.SortOrder != nil { + switch *req.SortOrder { + case "asc", "ascend", "ascending": + options.SortOrder = task.SortAscend + case "desc", "descend", "descending": + options.SortOrder = task.SortDescend + default: + return nil, makeInvalidInputErr(fmt.Errorf("invalid sort order %q", *req.SortOrder)) + } + } + + tasks, err := s.taskSvc.GetTasks(ctx, scope, entityID, options) + if err != nil { + return nil, apiErr(err) + } + + return &api.ListTasksResponse{ + Tasks: tasksToAPI(tasks), + }, nil +} diff --git a/server/internal/api/apiv1/pre_init_handlers.go b/server/internal/api/apiv1/pre_init_handlers.go index 00fb55a8..3e4ff04d 100644 --- a/server/internal/api/apiv1/pre_init_handlers.go +++ b/server/internal/api/apiv1/pre_init_handlers.go @@ -271,6 +271,22 @@ func (s *PreInitHandlers) CancelDatabaseTask(ctx context.Context, req *api.Cance return nil, ErrUninitialized } +func (s *PreInitHandlers) ListHostTasks(ctx context.Context, req *api.ListHostTasksPayload) (*api.ListHostTasksResponse, error) { + return nil, ErrUninitialized +} + +func (s *PreInitHandlers) GetHostTask(ctx context.Context, req *api.GetHostTaskPayload) (*api.Task, error) { + return nil, ErrUninitialized +} + +func (s *PreInitHandlers) GetHostTaskLog(ctx context.Context, req *api.GetHostTaskLogPayload) (*api.TaskLog, error) { + return nil, ErrUninitialized +} + +func (s *PreInitHandlers) ListTasks(ctx context.Context, req *api.ListTasksPayload) (*api.ListTasksResponse, error) { + return nil, ErrUninitialized +} + func (s *PreInitHandlers) GetClient() (res *http.Client, err error) { if s.cfg.HTTP.ClientCert == "" { return http.DefaultClient, nil