From 8764b4052f192000a5e37a069c7cb3ef4bc6ebf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Thu, 5 Mar 2026 15:58:29 -0800 Subject: [PATCH 1/2] feat(sdk): add agent state, conditions, drain/undrain, and timeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add State, Conditions, and Timeline fields to the Agent domain type. Add Drain() and Undrain() methods to AgentService for managing agent job acceptance. Add ConflictError (409) to the typed error hierarchy. Move TimelineEvent to shared types.go since it is used by both agent and job types. Regenerate client from updated API spec. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- docs/gen/gen.md | 834 +++++++++++++++++++++----------- docs/gen/osapi.md | 102 +++- pkg/osapi/agent.go | 62 +++ pkg/osapi/agent_public_test.go | 280 +++++++++++ pkg/osapi/agent_types.go | 60 +++ pkg/osapi/agent_types_test.go | 55 +++ pkg/osapi/errors.go | 10 + pkg/osapi/errors_public_test.go | 45 ++ pkg/osapi/gen/api.yaml | 164 +++++++ pkg/osapi/gen/client.gen.go | 340 ++++++++++++- pkg/osapi/job_types.go | 9 - pkg/osapi/response.go | 2 + pkg/osapi/response_test.go | 26 + pkg/osapi/types.go | 31 ++ 14 files changed, 1703 insertions(+), 317 deletions(-) create mode 100644 pkg/osapi/types.go diff --git a/docs/gen/gen.md b/docs/gen/gen.md index aa7d121..a8bec70 100644 --- a/docs/gen/gen.md +++ b/docs/gen/gen.md @@ -16,6 +16,7 @@ Package gen contains generated code for the OSAPI REST API client. - [Constants](<#constants>) - [func NewDeleteJobByIDRequest\(server string, id openapi\_types.UUID\) \(\*http.Request, error\)](<#NewDeleteJobByIDRequest>) +- [func NewDrainAgentRequest\(server string, hostname string\) \(\*http.Request, error\)](<#NewDrainAgentRequest>) - [func NewGetAgentDetailsRequest\(server string, hostname string\) \(\*http.Request, error\)](<#NewGetAgentDetailsRequest>) - [func NewGetAgentRequest\(server string\) \(\*http.Request, error\)](<#NewGetAgentRequest>) - [func NewGetAuditExportRequest\(server string\) \(\*http.Request, error\)](<#NewGetAuditExportRequest>) @@ -48,8 +49,10 @@ Package gen contains generated code for the OSAPI REST API client. - [func NewPutNodeNetworkDNSRequestWithBody\(server string, hostname Hostname, contentType string, body io.Reader\) \(\*http.Request, error\)](<#NewPutNodeNetworkDNSRequestWithBody>) - [func NewRetryJobByIDRequest\(server string, id openapi\_types.UUID, body RetryJobByIDJSONRequestBody\) \(\*http.Request, error\)](<#NewRetryJobByIDRequest>) - [func NewRetryJobByIDRequestWithBody\(server string, id openapi\_types.UUID, contentType string, body io.Reader\) \(\*http.Request, error\)](<#NewRetryJobByIDRequestWithBody>) +- [func NewUndrainAgentRequest\(server string, hostname string\) \(\*http.Request, error\)](<#NewUndrainAgentRequest>) - [type AgentDetail](<#AgentDetail>) - [type AgentInfo](<#AgentInfo>) +- [type AgentInfoState](<#AgentInfoState>) - [type AgentInfoStatus](<#AgentInfoStatus>) - [type AgentStats](<#AgentStats>) - [type AuditEntry](<#AuditEntry>) @@ -57,6 +60,7 @@ Package gen contains generated code for the OSAPI REST API client. - [type Client](<#Client>) - [func NewClient\(server string, opts ...ClientOption\) \(\*Client, error\)](<#NewClient>) - [func \(c \*Client\) DeleteJobByID\(ctx context.Context, id openapi\_types.UUID, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.DeleteJobByID>) + - [func \(c \*Client\) DrainAgent\(ctx context.Context, hostname string, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.DrainAgent>) - [func \(c \*Client\) GetAgent\(ctx context.Context, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.GetAgent>) - [func \(c \*Client\) GetAgentDetails\(ctx context.Context, hostname string, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.GetAgentDetails>) - [func \(c \*Client\) GetAuditExport\(ctx context.Context, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.GetAuditExport>) @@ -89,6 +93,7 @@ Package gen contains generated code for the OSAPI REST API client. - [func \(c \*Client\) PutNodeNetworkDNSWithBody\(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.PutNodeNetworkDNSWithBody>) - [func \(c \*Client\) RetryJobByID\(ctx context.Context, id openapi\_types.UUID, body RetryJobByIDJSONRequestBody, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.RetryJobByID>) - [func \(c \*Client\) RetryJobByIDWithBody\(ctx context.Context, id openapi\_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.RetryJobByIDWithBody>) + - [func \(c \*Client\) UndrainAgent\(ctx context.Context, hostname string, reqEditors ...RequestEditorFn\) \(\*http.Response, error\)](<#Client.UndrainAgent>) - [type ClientInterface](<#ClientInterface>) - [type ClientOption](<#ClientOption>) - [func WithBaseURL\(baseURL string\) ClientOption](<#WithBaseURL>) @@ -97,6 +102,7 @@ Package gen contains generated code for the OSAPI REST API client. - [type ClientWithResponses](<#ClientWithResponses>) - [func NewClientWithResponses\(server string, opts ...ClientOption\) \(\*ClientWithResponses, error\)](<#NewClientWithResponses>) - [func \(c \*ClientWithResponses\) DeleteJobByIDWithResponse\(ctx context.Context, id openapi\_types.UUID, reqEditors ...RequestEditorFn\) \(\*DeleteJobByIDResponse, error\)](<#ClientWithResponses.DeleteJobByIDWithResponse>) + - [func \(c \*ClientWithResponses\) DrainAgentWithResponse\(ctx context.Context, hostname string, reqEditors ...RequestEditorFn\) \(\*DrainAgentResponse, error\)](<#ClientWithResponses.DrainAgentWithResponse>) - [func \(c \*ClientWithResponses\) GetAgentDetailsWithResponse\(ctx context.Context, hostname string, reqEditors ...RequestEditorFn\) \(\*GetAgentDetailsResponse, error\)](<#ClientWithResponses.GetAgentDetailsWithResponse>) - [func \(c \*ClientWithResponses\) GetAgentWithResponse\(ctx context.Context, reqEditors ...RequestEditorFn\) \(\*GetAgentResponse, error\)](<#ClientWithResponses.GetAgentWithResponse>) - [func \(c \*ClientWithResponses\) GetAuditExportWithResponse\(ctx context.Context, reqEditors ...RequestEditorFn\) \(\*GetAuditExportResponse, error\)](<#ClientWithResponses.GetAuditExportWithResponse>) @@ -129,6 +135,7 @@ Package gen contains generated code for the OSAPI REST API client. - [func \(c \*ClientWithResponses\) PutNodeNetworkDNSWithResponse\(ctx context.Context, hostname Hostname, body PutNodeNetworkDNSJSONRequestBody, reqEditors ...RequestEditorFn\) \(\*PutNodeNetworkDNSResponse, error\)](<#ClientWithResponses.PutNodeNetworkDNSWithResponse>) - [func \(c \*ClientWithResponses\) RetryJobByIDWithBodyWithResponse\(ctx context.Context, id openapi\_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn\) \(\*RetryJobByIDResponse, error\)](<#ClientWithResponses.RetryJobByIDWithBodyWithResponse>) - [func \(c \*ClientWithResponses\) RetryJobByIDWithResponse\(ctx context.Context, id openapi\_types.UUID, body RetryJobByIDJSONRequestBody, reqEditors ...RequestEditorFn\) \(\*RetryJobByIDResponse, error\)](<#ClientWithResponses.RetryJobByIDWithResponse>) + - [func \(c \*ClientWithResponses\) UndrainAgentWithResponse\(ctx context.Context, hostname string, reqEditors ...RequestEditorFn\) \(\*UndrainAgentResponse, error\)](<#ClientWithResponses.UndrainAgentWithResponse>) - [type ClientWithResponsesInterface](<#ClientWithResponsesInterface>) - [type CommandExecRequest](<#CommandExecRequest>) - [type CommandResultCollectionResponse](<#CommandResultCollectionResponse>) @@ -153,6 +160,10 @@ Package gen contains generated code for the OSAPI REST API client. - [type DiskResponse](<#DiskResponse>) - [type DiskResultItem](<#DiskResultItem>) - [type DisksResponse](<#DisksResponse>) +- [type DrainAgentResponse](<#DrainAgentResponse>) + - [func ParseDrainAgentResponse\(rsp \*http.Response\) \(\*DrainAgentResponse, error\)](<#ParseDrainAgentResponse>) + - [func \(r DrainAgentResponse\) Status\(\) string](<#DrainAgentResponse.Status>) + - [func \(r DrainAgentResponse\) StatusCode\(\) int](<#DrainAgentResponse.StatusCode>) - [type ErrorResponse](<#ErrorResponse>) - [type GetAgentDetailsResponse](<#GetAgentDetailsResponse>) - [func ParseGetAgentDetailsResponse\(rsp \*http.Response\) \(\*GetAgentDetailsResponse, error\)](<#ParseGetAgentDetailsResponse>) @@ -257,6 +268,8 @@ Package gen contains generated code for the OSAPI REST API client. - [type NATSInfo](<#NATSInfo>) - [type NetworkInterfaceResponse](<#NetworkInterfaceResponse>) - [type NetworkInterfaceResponseFamily](<#NetworkInterfaceResponseFamily>) +- [type NodeCondition](<#NodeCondition>) +- [type NodeConditionType](<#NodeConditionType>) - [type NodeStatusCollectionResponse](<#NodeStatusCollectionResponse>) - [type NodeStatusResponse](<#NodeStatusResponse>) - [type OSInfoCollectionResponse](<#OSInfoCollectionResponse>) @@ -301,6 +314,11 @@ Package gen contains generated code for the OSAPI REST API client. - [type RetryJobRequest](<#RetryJobRequest>) - [type StatusResponse](<#StatusResponse>) - [type StreamInfo](<#StreamInfo>) +- [type TimelineEvent](<#TimelineEvent>) +- [type UndrainAgentResponse](<#UndrainAgentResponse>) + - [func ParseUndrainAgentResponse\(rsp \*http.Response\) \(\*UndrainAgentResponse, error\)](<#ParseUndrainAgentResponse>) + - [func \(r UndrainAgentResponse\) Status\(\) string](<#UndrainAgentResponse.Status>) + - [func \(r UndrainAgentResponse\) StatusCode\(\) int](<#UndrainAgentResponse.StatusCode>) - [type UptimeCollectionResponse](<#UptimeCollectionResponse>) - [type UptimeResponse](<#UptimeResponse>) @@ -316,7 +334,7 @@ const ( ``` -## func [NewDeleteJobByIDRequest]() +## func [NewDeleteJobByIDRequest]() ```go func NewDeleteJobByIDRequest(server string, id openapi_types.UUID) (*http.Request, error) @@ -324,8 +342,17 @@ func NewDeleteJobByIDRequest(server string, id openapi_types.UUID) (*http.Reques NewDeleteJobByIDRequest generates requests for DeleteJobByID + +## func [NewDrainAgentRequest]() + +```go +func NewDrainAgentRequest(server string, hostname string) (*http.Request, error) +``` + +NewDrainAgentRequest generates requests for DrainAgent + -## func [NewGetAgentDetailsRequest]() +## func [NewGetAgentDetailsRequest]() ```go func NewGetAgentDetailsRequest(server string, hostname string) (*http.Request, error) @@ -334,7 +361,7 @@ func NewGetAgentDetailsRequest(server string, hostname string) (*http.Request, e NewGetAgentDetailsRequest generates requests for GetAgentDetails -## func [NewGetAgentRequest]() +## func [NewGetAgentRequest]() ```go func NewGetAgentRequest(server string) (*http.Request, error) @@ -343,7 +370,7 @@ func NewGetAgentRequest(server string) (*http.Request, error) NewGetAgentRequest generates requests for GetAgent -## func [NewGetAuditExportRequest]() +## func [NewGetAuditExportRequest]() ```go func NewGetAuditExportRequest(server string) (*http.Request, error) @@ -352,7 +379,7 @@ func NewGetAuditExportRequest(server string) (*http.Request, error) NewGetAuditExportRequest generates requests for GetAuditExport -## func [NewGetAuditLogByIDRequest]() +## func [NewGetAuditLogByIDRequest]() ```go func NewGetAuditLogByIDRequest(server string, id openapi_types.UUID) (*http.Request, error) @@ -361,7 +388,7 @@ func NewGetAuditLogByIDRequest(server string, id openapi_types.UUID) (*http.Requ NewGetAuditLogByIDRequest generates requests for GetAuditLogByID -## func [NewGetAuditLogsRequest]() +## func [NewGetAuditLogsRequest]() ```go func NewGetAuditLogsRequest(server string, params *GetAuditLogsParams) (*http.Request, error) @@ -370,7 +397,7 @@ func NewGetAuditLogsRequest(server string, params *GetAuditLogsParams) (*http.Re NewGetAuditLogsRequest generates requests for GetAuditLogs -## func [NewGetHealthReadyRequest]() +## func [NewGetHealthReadyRequest]() ```go func NewGetHealthReadyRequest(server string) (*http.Request, error) @@ -379,7 +406,7 @@ func NewGetHealthReadyRequest(server string) (*http.Request, error) NewGetHealthReadyRequest generates requests for GetHealthReady -## func [NewGetHealthRequest]() +## func [NewGetHealthRequest]() ```go func NewGetHealthRequest(server string) (*http.Request, error) @@ -388,7 +415,7 @@ func NewGetHealthRequest(server string) (*http.Request, error) NewGetHealthRequest generates requests for GetHealth -## func [NewGetHealthStatusRequest]() +## func [NewGetHealthStatusRequest]() ```go func NewGetHealthStatusRequest(server string) (*http.Request, error) @@ -397,7 +424,7 @@ func NewGetHealthStatusRequest(server string) (*http.Request, error) NewGetHealthStatusRequest generates requests for GetHealthStatus -## func [NewGetJobByIDRequest]() +## func [NewGetJobByIDRequest]() ```go func NewGetJobByIDRequest(server string, id openapi_types.UUID) (*http.Request, error) @@ -406,7 +433,7 @@ func NewGetJobByIDRequest(server string, id openapi_types.UUID) (*http.Request, NewGetJobByIDRequest generates requests for GetJobByID -## func [NewGetJobRequest]() +## func [NewGetJobRequest]() ```go func NewGetJobRequest(server string, params *GetJobParams) (*http.Request, error) @@ -415,7 +442,7 @@ func NewGetJobRequest(server string, params *GetJobParams) (*http.Request, error NewGetJobRequest generates requests for GetJob -## func [NewGetJobStatusRequest]() +## func [NewGetJobStatusRequest]() ```go func NewGetJobStatusRequest(server string) (*http.Request, error) @@ -424,7 +451,7 @@ func NewGetJobStatusRequest(server string) (*http.Request, error) NewGetJobStatusRequest generates requests for GetJobStatus -## func [NewGetNodeDiskRequest]() +## func [NewGetNodeDiskRequest]() ```go func NewGetNodeDiskRequest(server string, hostname Hostname) (*http.Request, error) @@ -433,7 +460,7 @@ func NewGetNodeDiskRequest(server string, hostname Hostname) (*http.Request, err NewGetNodeDiskRequest generates requests for GetNodeDisk -## func [NewGetNodeHostnameRequest]() +## func [NewGetNodeHostnameRequest]() ```go func NewGetNodeHostnameRequest(server string, hostname Hostname) (*http.Request, error) @@ -442,7 +469,7 @@ func NewGetNodeHostnameRequest(server string, hostname Hostname) (*http.Request, NewGetNodeHostnameRequest generates requests for GetNodeHostname -## func [NewGetNodeLoadRequest]() +## func [NewGetNodeLoadRequest]() ```go func NewGetNodeLoadRequest(server string, hostname Hostname) (*http.Request, error) @@ -451,7 +478,7 @@ func NewGetNodeLoadRequest(server string, hostname Hostname) (*http.Request, err NewGetNodeLoadRequest generates requests for GetNodeLoad -## func [NewGetNodeMemoryRequest]() +## func [NewGetNodeMemoryRequest]() ```go func NewGetNodeMemoryRequest(server string, hostname Hostname) (*http.Request, error) @@ -460,7 +487,7 @@ func NewGetNodeMemoryRequest(server string, hostname Hostname) (*http.Request, e NewGetNodeMemoryRequest generates requests for GetNodeMemory -## func [NewGetNodeNetworkDNSByInterfaceRequest]() +## func [NewGetNodeNetworkDNSByInterfaceRequest]() ```go func NewGetNodeNetworkDNSByInterfaceRequest(server string, hostname Hostname, interfaceName string) (*http.Request, error) @@ -469,7 +496,7 @@ func NewGetNodeNetworkDNSByInterfaceRequest(server string, hostname Hostname, in NewGetNodeNetworkDNSByInterfaceRequest generates requests for GetNodeNetworkDNSByInterface -## func [NewGetNodeOSRequest]() +## func [NewGetNodeOSRequest]() ```go func NewGetNodeOSRequest(server string, hostname Hostname) (*http.Request, error) @@ -478,7 +505,7 @@ func NewGetNodeOSRequest(server string, hostname Hostname) (*http.Request, error NewGetNodeOSRequest generates requests for GetNodeOS -## func [NewGetNodeStatusRequest]() +## func [NewGetNodeStatusRequest]() ```go func NewGetNodeStatusRequest(server string, hostname Hostname) (*http.Request, error) @@ -487,7 +514,7 @@ func NewGetNodeStatusRequest(server string, hostname Hostname) (*http.Request, e NewGetNodeStatusRequest generates requests for GetNodeStatus -## func [NewGetNodeUptimeRequest]() +## func [NewGetNodeUptimeRequest]() ```go func NewGetNodeUptimeRequest(server string, hostname Hostname) (*http.Request, error) @@ -496,7 +523,7 @@ func NewGetNodeUptimeRequest(server string, hostname Hostname) (*http.Request, e NewGetNodeUptimeRequest generates requests for GetNodeUptime -## func [NewGetVersionRequest]() +## func [NewGetVersionRequest]() ```go func NewGetVersionRequest(server string) (*http.Request, error) @@ -505,7 +532,7 @@ func NewGetVersionRequest(server string) (*http.Request, error) NewGetVersionRequest generates requests for GetVersion -## func [NewPostJobRequest]() +## func [NewPostJobRequest]() ```go func NewPostJobRequest(server string, body PostJobJSONRequestBody) (*http.Request, error) @@ -514,7 +541,7 @@ func NewPostJobRequest(server string, body PostJobJSONRequestBody) (*http.Reques NewPostJobRequest calls the generic PostJob builder with application/json body -## func [NewPostJobRequestWithBody]() +## func [NewPostJobRequestWithBody]() ```go func NewPostJobRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) @@ -523,7 +550,7 @@ func NewPostJobRequestWithBody(server string, contentType string, body io.Reader NewPostJobRequestWithBody generates requests for PostJob with any type of body -## func [NewPostNodeCommandExecRequest]() +## func [NewPostNodeCommandExecRequest]() ```go func NewPostNodeCommandExecRequest(server string, hostname Hostname, body PostNodeCommandExecJSONRequestBody) (*http.Request, error) @@ -532,7 +559,7 @@ func NewPostNodeCommandExecRequest(server string, hostname Hostname, body PostNo NewPostNodeCommandExecRequest calls the generic PostNodeCommandExec builder with application/json body -## func [NewPostNodeCommandExecRequestWithBody]() +## func [NewPostNodeCommandExecRequestWithBody]() ```go func NewPostNodeCommandExecRequestWithBody(server string, hostname Hostname, contentType string, body io.Reader) (*http.Request, error) @@ -541,7 +568,7 @@ func NewPostNodeCommandExecRequestWithBody(server string, hostname Hostname, con NewPostNodeCommandExecRequestWithBody generates requests for PostNodeCommandExec with any type of body -## func [NewPostNodeCommandShellRequest]() +## func [NewPostNodeCommandShellRequest]() ```go func NewPostNodeCommandShellRequest(server string, hostname Hostname, body PostNodeCommandShellJSONRequestBody) (*http.Request, error) @@ -550,7 +577,7 @@ func NewPostNodeCommandShellRequest(server string, hostname Hostname, body PostN NewPostNodeCommandShellRequest calls the generic PostNodeCommandShell builder with application/json body -## func [NewPostNodeCommandShellRequestWithBody]() +## func [NewPostNodeCommandShellRequestWithBody]() ```go func NewPostNodeCommandShellRequestWithBody(server string, hostname Hostname, contentType string, body io.Reader) (*http.Request, error) @@ -559,7 +586,7 @@ func NewPostNodeCommandShellRequestWithBody(server string, hostname Hostname, co NewPostNodeCommandShellRequestWithBody generates requests for PostNodeCommandShell with any type of body -## func [NewPostNodeNetworkPingRequest]() +## func [NewPostNodeNetworkPingRequest]() ```go func NewPostNodeNetworkPingRequest(server string, hostname Hostname, body PostNodeNetworkPingJSONRequestBody) (*http.Request, error) @@ -568,7 +595,7 @@ func NewPostNodeNetworkPingRequest(server string, hostname Hostname, body PostNo NewPostNodeNetworkPingRequest calls the generic PostNodeNetworkPing builder with application/json body -## func [NewPostNodeNetworkPingRequestWithBody]() +## func [NewPostNodeNetworkPingRequestWithBody]() ```go func NewPostNodeNetworkPingRequestWithBody(server string, hostname Hostname, contentType string, body io.Reader) (*http.Request, error) @@ -577,7 +604,7 @@ func NewPostNodeNetworkPingRequestWithBody(server string, hostname Hostname, con NewPostNodeNetworkPingRequestWithBody generates requests for PostNodeNetworkPing with any type of body -## func [NewPutNodeNetworkDNSRequest]() +## func [NewPutNodeNetworkDNSRequest]() ```go func NewPutNodeNetworkDNSRequest(server string, hostname Hostname, body PutNodeNetworkDNSJSONRequestBody) (*http.Request, error) @@ -586,7 +613,7 @@ func NewPutNodeNetworkDNSRequest(server string, hostname Hostname, body PutNodeN NewPutNodeNetworkDNSRequest calls the generic PutNodeNetworkDNS builder with application/json body -## func [NewPutNodeNetworkDNSRequestWithBody]() +## func [NewPutNodeNetworkDNSRequestWithBody]() ```go func NewPutNodeNetworkDNSRequestWithBody(server string, hostname Hostname, contentType string, body io.Reader) (*http.Request, error) @@ -595,7 +622,7 @@ func NewPutNodeNetworkDNSRequestWithBody(server string, hostname Hostname, conte NewPutNodeNetworkDNSRequestWithBody generates requests for PutNodeNetworkDNS with any type of body -## func [NewRetryJobByIDRequest]() +## func [NewRetryJobByIDRequest]() ```go func NewRetryJobByIDRequest(server string, id openapi_types.UUID, body RetryJobByIDJSONRequestBody) (*http.Request, error) @@ -604,7 +631,7 @@ func NewRetryJobByIDRequest(server string, id openapi_types.UUID, body RetryJobB NewRetryJobByIDRequest calls the generic RetryJobByID builder with application/json body -## func [NewRetryJobByIDRequestWithBody]() +## func [NewRetryJobByIDRequestWithBody]() ```go func NewRetryJobByIDRequestWithBody(server string, id openapi_types.UUID, contentType string, body io.Reader) (*http.Request, error) @@ -612,8 +639,17 @@ func NewRetryJobByIDRequestWithBody(server string, id openapi_types.UUID, conten NewRetryJobByIDRequestWithBody generates requests for RetryJobByID with any type of body + +## func [NewUndrainAgentRequest]() + +```go +func NewUndrainAgentRequest(server string, hostname string) (*http.Request, error) +``` + +NewUndrainAgentRequest generates requests for UndrainAgent + -## type [AgentDetail]() +## type [AgentDetail]() AgentDetail defines model for AgentDetail. @@ -631,7 +667,7 @@ type AgentDetail struct { ``` -## type [AgentInfo]() +## type [AgentInfo]() AgentInfo defines model for AgentInfo. @@ -640,6 +676,9 @@ type AgentInfo struct { // Architecture CPU architecture. Architecture *string `json:"architecture,omitempty"` + // Conditions Evaluated node conditions. + Conditions *[]NodeCondition `json:"conditions,omitempty"` + // CpuCount Number of logical CPUs. CpuCount *int `json:"cpu_count,omitempty"` @@ -680,16 +719,41 @@ type AgentInfo struct { // StartedAt When the agent process started. StartedAt *time.Time `json:"started_at,omitempty"` + // State Agent scheduling state. + State *AgentInfoState `json:"state,omitempty"` + // Status The current status of the agent. Status AgentInfoStatus `json:"status"` + // Timeline Agent state transition history. + Timeline *[]TimelineEvent `json:"timeline,omitempty"` + // Uptime The system uptime. Uptime *string `json:"uptime,omitempty"` } ``` + +## type [AgentInfoState]() + +AgentInfoState Agent scheduling state. + +```go +type AgentInfoState string +``` + +Defines values for AgentInfoState. + +```go +const ( + AgentInfoStateCordoned AgentInfoState = "Cordoned" + AgentInfoStateDraining AgentInfoState = "Draining" + AgentInfoStateReady AgentInfoState = "Ready" +) +``` + -## type [AgentInfoStatus]() +## type [AgentInfoStatus]() AgentInfoStatus The current status of the agent. @@ -697,17 +761,17 @@ AgentInfoStatus The current status of the agent. type AgentInfoStatus string ``` -Defines values for AgentInfoStatus. +Defines values for AgentInfoStatus. ```go const ( - NotReady AgentInfoStatus = "NotReady" - Ready AgentInfoStatus = "Ready" + AgentInfoStatusNotReady AgentInfoStatus = "NotReady" + AgentInfoStatusReady AgentInfoStatus = "Ready" ) ``` -## type [AgentStats]() +## type [AgentStats]() AgentStats defines model for AgentStats. @@ -725,7 +789,7 @@ type AgentStats struct { ``` -## type [AuditEntry]() +## type [AuditEntry]() AuditEntry defines model for AuditEntry. @@ -764,7 +828,7 @@ type AuditEntry struct { ``` -## type [AuditEntryResponse]() +## type [AuditEntryResponse]() AuditEntryResponse defines model for AuditEntryResponse. @@ -775,7 +839,7 @@ type AuditEntryResponse struct { ``` -## type [Client]() +## type [Client]() Client which conforms to the OpenAPI3 specification for this service. @@ -798,7 +862,7 @@ type Client struct { ``` -### func [NewClient]() +### func [NewClient]() ```go func NewClient(server string, opts ...ClientOption) (*Client, error) @@ -807,7 +871,7 @@ func NewClient(server string, opts ...ClientOption) (*Client, error) Creates a new Client, with reasonable defaults -### func \(\*Client\) [DeleteJobByID]() +### func \(\*Client\) [DeleteJobByID]() ```go func (c *Client) DeleteJobByID(ctx context.Context, id openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -815,8 +879,17 @@ func (c *Client) DeleteJobByID(ctx context.Context, id openapi_types.UUID, reqEd + +### func \(\*Client\) [DrainAgent]() + +```go +func (c *Client) DrainAgent(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) +``` + + + -### func \(\*Client\) [GetAgent]() +### func \(\*Client\) [GetAgent]() ```go func (c *Client) GetAgent(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -825,7 +898,7 @@ func (c *Client) GetAgent(ctx context.Context, reqEditors ...RequestEditorFn) (* -### func \(\*Client\) [GetAgentDetails]() +### func \(\*Client\) [GetAgentDetails]() ```go func (c *Client) GetAgentDetails(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -834,7 +907,7 @@ func (c *Client) GetAgentDetails(ctx context.Context, hostname string, reqEditor -### func \(\*Client\) [GetAuditExport]() +### func \(\*Client\) [GetAuditExport]() ```go func (c *Client) GetAuditExport(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -843,7 +916,7 @@ func (c *Client) GetAuditExport(ctx context.Context, reqEditors ...RequestEditor -### func \(\*Client\) [GetAuditLogByID]() +### func \(\*Client\) [GetAuditLogByID]() ```go func (c *Client) GetAuditLogByID(ctx context.Context, id openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -852,7 +925,7 @@ func (c *Client) GetAuditLogByID(ctx context.Context, id openapi_types.UUID, req -### func \(\*Client\) [GetAuditLogs]() +### func \(\*Client\) [GetAuditLogs]() ```go func (c *Client) GetAuditLogs(ctx context.Context, params *GetAuditLogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -861,7 +934,7 @@ func (c *Client) GetAuditLogs(ctx context.Context, params *GetAuditLogsParams, r -### func \(\*Client\) [GetHealth]() +### func \(\*Client\) [GetHealth]() ```go func (c *Client) GetHealth(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -870,7 +943,7 @@ func (c *Client) GetHealth(ctx context.Context, reqEditors ...RequestEditorFn) ( -### func \(\*Client\) [GetHealthReady]() +### func \(\*Client\) [GetHealthReady]() ```go func (c *Client) GetHealthReady(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -879,7 +952,7 @@ func (c *Client) GetHealthReady(ctx context.Context, reqEditors ...RequestEditor -### func \(\*Client\) [GetHealthStatus]() +### func \(\*Client\) [GetHealthStatus]() ```go func (c *Client) GetHealthStatus(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -888,7 +961,7 @@ func (c *Client) GetHealthStatus(ctx context.Context, reqEditors ...RequestEdito -### func \(\*Client\) [GetJob]() +### func \(\*Client\) [GetJob]() ```go func (c *Client) GetJob(ctx context.Context, params *GetJobParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -897,7 +970,7 @@ func (c *Client) GetJob(ctx context.Context, params *GetJobParams, reqEditors .. -### func \(\*Client\) [GetJobByID]() +### func \(\*Client\) [GetJobByID]() ```go func (c *Client) GetJobByID(ctx context.Context, id openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -906,7 +979,7 @@ func (c *Client) GetJobByID(ctx context.Context, id openapi_types.UUID, reqEdito -### func \(\*Client\) [GetJobStatus]() +### func \(\*Client\) [GetJobStatus]() ```go func (c *Client) GetJobStatus(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -915,7 +988,7 @@ func (c *Client) GetJobStatus(ctx context.Context, reqEditors ...RequestEditorFn -### func \(\*Client\) [GetNodeDisk]() +### func \(\*Client\) [GetNodeDisk]() ```go func (c *Client) GetNodeDisk(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -924,7 +997,7 @@ func (c *Client) GetNodeDisk(ctx context.Context, hostname Hostname, reqEditors -### func \(\*Client\) [GetNodeHostname]() +### func \(\*Client\) [GetNodeHostname]() ```go func (c *Client) GetNodeHostname(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -933,7 +1006,7 @@ func (c *Client) GetNodeHostname(ctx context.Context, hostname Hostname, reqEdit -### func \(\*Client\) [GetNodeLoad]() +### func \(\*Client\) [GetNodeLoad]() ```go func (c *Client) GetNodeLoad(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -942,7 +1015,7 @@ func (c *Client) GetNodeLoad(ctx context.Context, hostname Hostname, reqEditors -### func \(\*Client\) [GetNodeMemory]() +### func \(\*Client\) [GetNodeMemory]() ```go func (c *Client) GetNodeMemory(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -951,7 +1024,7 @@ func (c *Client) GetNodeMemory(ctx context.Context, hostname Hostname, reqEditor -### func \(\*Client\) [GetNodeNetworkDNSByInterface]() +### func \(\*Client\) [GetNodeNetworkDNSByInterface]() ```go func (c *Client) GetNodeNetworkDNSByInterface(ctx context.Context, hostname Hostname, interfaceName string, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -960,7 +1033,7 @@ func (c *Client) GetNodeNetworkDNSByInterface(ctx context.Context, hostname Host -### func \(\*Client\) [GetNodeOS]() +### func \(\*Client\) [GetNodeOS]() ```go func (c *Client) GetNodeOS(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -969,7 +1042,7 @@ func (c *Client) GetNodeOS(ctx context.Context, hostname Hostname, reqEditors .. -### func \(\*Client\) [GetNodeStatus]() +### func \(\*Client\) [GetNodeStatus]() ```go func (c *Client) GetNodeStatus(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -978,7 +1051,7 @@ func (c *Client) GetNodeStatus(ctx context.Context, hostname Hostname, reqEditor -### func \(\*Client\) [GetNodeUptime]() +### func \(\*Client\) [GetNodeUptime]() ```go func (c *Client) GetNodeUptime(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -987,7 +1060,7 @@ func (c *Client) GetNodeUptime(ctx context.Context, hostname Hostname, reqEditor -### func \(\*Client\) [GetVersion]() +### func \(\*Client\) [GetVersion]() ```go func (c *Client) GetVersion(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -996,7 +1069,7 @@ func (c *Client) GetVersion(ctx context.Context, reqEditors ...RequestEditorFn) -### func \(\*Client\) [PostJob]() +### func \(\*Client\) [PostJob]() ```go func (c *Client) PostJob(ctx context.Context, body PostJobJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1005,7 +1078,7 @@ func (c *Client) PostJob(ctx context.Context, body PostJobJSONRequestBody, reqEd -### func \(\*Client\) [PostJobWithBody]() +### func \(\*Client\) [PostJobWithBody]() ```go func (c *Client) PostJobWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1014,7 +1087,7 @@ func (c *Client) PostJobWithBody(ctx context.Context, contentType string, body i -### func \(\*Client\) [PostNodeCommandExec]() +### func \(\*Client\) [PostNodeCommandExec]() ```go func (c *Client) PostNodeCommandExec(ctx context.Context, hostname Hostname, body PostNodeCommandExecJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1023,7 +1096,7 @@ func (c *Client) PostNodeCommandExec(ctx context.Context, hostname Hostname, bod -### func \(\*Client\) [PostNodeCommandExecWithBody]() +### func \(\*Client\) [PostNodeCommandExecWithBody]() ```go func (c *Client) PostNodeCommandExecWithBody(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1032,7 +1105,7 @@ func (c *Client) PostNodeCommandExecWithBody(ctx context.Context, hostname Hostn -### func \(\*Client\) [PostNodeCommandShell]() +### func \(\*Client\) [PostNodeCommandShell]() ```go func (c *Client) PostNodeCommandShell(ctx context.Context, hostname Hostname, body PostNodeCommandShellJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1041,7 +1114,7 @@ func (c *Client) PostNodeCommandShell(ctx context.Context, hostname Hostname, bo -### func \(\*Client\) [PostNodeCommandShellWithBody]() +### func \(\*Client\) [PostNodeCommandShellWithBody]() ```go func (c *Client) PostNodeCommandShellWithBody(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1050,7 +1123,7 @@ func (c *Client) PostNodeCommandShellWithBody(ctx context.Context, hostname Host -### func \(\*Client\) [PostNodeNetworkPing]() +### func \(\*Client\) [PostNodeNetworkPing]() ```go func (c *Client) PostNodeNetworkPing(ctx context.Context, hostname Hostname, body PostNodeNetworkPingJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1059,7 +1132,7 @@ func (c *Client) PostNodeNetworkPing(ctx context.Context, hostname Hostname, bod -### func \(\*Client\) [PostNodeNetworkPingWithBody]() +### func \(\*Client\) [PostNodeNetworkPingWithBody]() ```go func (c *Client) PostNodeNetworkPingWithBody(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1068,7 +1141,7 @@ func (c *Client) PostNodeNetworkPingWithBody(ctx context.Context, hostname Hostn -### func \(\*Client\) [PutNodeNetworkDNS]() +### func \(\*Client\) [PutNodeNetworkDNS]() ```go func (c *Client) PutNodeNetworkDNS(ctx context.Context, hostname Hostname, body PutNodeNetworkDNSJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1077,7 +1150,7 @@ func (c *Client) PutNodeNetworkDNS(ctx context.Context, hostname Hostname, body -### func \(\*Client\) [PutNodeNetworkDNSWithBody]() +### func \(\*Client\) [PutNodeNetworkDNSWithBody]() ```go func (c *Client) PutNodeNetworkDNSWithBody(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1086,7 +1159,7 @@ func (c *Client) PutNodeNetworkDNSWithBody(ctx context.Context, hostname Hostnam -### func \(\*Client\) [RetryJobByID]() +### func \(\*Client\) [RetryJobByID]() ```go func (c *Client) RetryJobByID(ctx context.Context, id openapi_types.UUID, body RetryJobByIDJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1095,7 +1168,7 @@ func (c *Client) RetryJobByID(ctx context.Context, id openapi_types.UUID, body R -### func \(\*Client\) [RetryJobByIDWithBody]() +### func \(\*Client\) [RetryJobByIDWithBody]() ```go func (c *Client) RetryJobByIDWithBody(ctx context.Context, id openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1103,8 +1176,17 @@ func (c *Client) RetryJobByIDWithBody(ctx context.Context, id openapi_types.UUID + +### func \(\*Client\) [UndrainAgent]() + +```go +func (c *Client) UndrainAgent(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) +``` + + + -## type [ClientInterface]() +## type [ClientInterface]() The interface specification for the client above. @@ -1116,6 +1198,12 @@ type ClientInterface interface { // GetAgentDetails request GetAgentDetails(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) + // DrainAgent request + DrainAgent(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // UndrainAgent request + UndrainAgent(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetAuditLogs request GetAuditLogs(ctx context.Context, params *GetAuditLogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1206,7 +1294,7 @@ type ClientInterface interface { ``` -## type [ClientOption]() +## type [ClientOption]() ClientOption allows setting custom parameters during construction @@ -1215,7 +1303,7 @@ type ClientOption func(*Client) error ``` -### func [WithBaseURL]() +### func [WithBaseURL]() ```go func WithBaseURL(baseURL string) ClientOption @@ -1224,7 +1312,7 @@ func WithBaseURL(baseURL string) ClientOption WithBaseURL overrides the baseURL. -### func [WithHTTPClient]() +### func [WithHTTPClient]() ```go func WithHTTPClient(doer HttpRequestDoer) ClientOption @@ -1233,7 +1321,7 @@ func WithHTTPClient(doer HttpRequestDoer) ClientOption WithHTTPClient allows overriding the default Doer, which is automatically created using http.Client. This is useful for tests. -### func [WithRequestEditorFn]() +### func [WithRequestEditorFn]() ```go func WithRequestEditorFn(fn RequestEditorFn) ClientOption @@ -1242,7 +1330,7 @@ func WithRequestEditorFn(fn RequestEditorFn) ClientOption WithRequestEditorFn allows setting up a callback function, which will be called right before sending the request. This can be used to mutate the request. -## type [ClientWithResponses]() +## type [ClientWithResponses]() ClientWithResponses builds on ClientInterface to offer response payloads @@ -1253,7 +1341,7 @@ type ClientWithResponses struct { ``` -### func [NewClientWithResponses]() +### func [NewClientWithResponses]() ```go func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) @@ -1262,7 +1350,7 @@ func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithRes NewClientWithResponses creates a new ClientWithResponses, which wraps Client with return type handling -### func \(\*ClientWithResponses\) [DeleteJobByIDWithResponse]() +### func \(\*ClientWithResponses\) [DeleteJobByIDWithResponse]() ```go func (c *ClientWithResponses) DeleteJobByIDWithResponse(ctx context.Context, id openapi_types.UUID, reqEditors ...RequestEditorFn) (*DeleteJobByIDResponse, error) @@ -1270,8 +1358,17 @@ func (c *ClientWithResponses) DeleteJobByIDWithResponse(ctx context.Context, id DeleteJobByIDWithResponse request returning \*DeleteJobByIDResponse + +### func \(\*ClientWithResponses\) [DrainAgentWithResponse]() + +```go +func (c *ClientWithResponses) DrainAgentWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*DrainAgentResponse, error) +``` + +DrainAgentWithResponse request returning \*DrainAgentResponse + -### func \(\*ClientWithResponses\) [GetAgentDetailsWithResponse]() +### func \(\*ClientWithResponses\) [GetAgentDetailsWithResponse]() ```go func (c *ClientWithResponses) GetAgentDetailsWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*GetAgentDetailsResponse, error) @@ -1280,7 +1377,7 @@ func (c *ClientWithResponses) GetAgentDetailsWithResponse(ctx context.Context, h GetAgentDetailsWithResponse request returning \*GetAgentDetailsResponse -### func \(\*ClientWithResponses\) [GetAgentWithResponse]() +### func \(\*ClientWithResponses\) [GetAgentWithResponse]() ```go func (c *ClientWithResponses) GetAgentWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetAgentResponse, error) @@ -1289,7 +1386,7 @@ func (c *ClientWithResponses) GetAgentWithResponse(ctx context.Context, reqEdito GetAgentWithResponse request returning \*GetAgentResponse -### func \(\*ClientWithResponses\) [GetAuditExportWithResponse]() +### func \(\*ClientWithResponses\) [GetAuditExportWithResponse]() ```go func (c *ClientWithResponses) GetAuditExportWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetAuditExportResponse, error) @@ -1298,7 +1395,7 @@ func (c *ClientWithResponses) GetAuditExportWithResponse(ctx context.Context, re GetAuditExportWithResponse request returning \*GetAuditExportResponse -### func \(\*ClientWithResponses\) [GetAuditLogByIDWithResponse]() +### func \(\*ClientWithResponses\) [GetAuditLogByIDWithResponse]() ```go func (c *ClientWithResponses) GetAuditLogByIDWithResponse(ctx context.Context, id openapi_types.UUID, reqEditors ...RequestEditorFn) (*GetAuditLogByIDResponse, error) @@ -1307,7 +1404,7 @@ func (c *ClientWithResponses) GetAuditLogByIDWithResponse(ctx context.Context, i GetAuditLogByIDWithResponse request returning \*GetAuditLogByIDResponse -### func \(\*ClientWithResponses\) [GetAuditLogsWithResponse]() +### func \(\*ClientWithResponses\) [GetAuditLogsWithResponse]() ```go func (c *ClientWithResponses) GetAuditLogsWithResponse(ctx context.Context, params *GetAuditLogsParams, reqEditors ...RequestEditorFn) (*GetAuditLogsResponse, error) @@ -1316,7 +1413,7 @@ func (c *ClientWithResponses) GetAuditLogsWithResponse(ctx context.Context, para GetAuditLogsWithResponse request returning \*GetAuditLogsResponse -### func \(\*ClientWithResponses\) [GetHealthReadyWithResponse]() +### func \(\*ClientWithResponses\) [GetHealthReadyWithResponse]() ```go func (c *ClientWithResponses) GetHealthReadyWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetHealthReadyResponse, error) @@ -1325,7 +1422,7 @@ func (c *ClientWithResponses) GetHealthReadyWithResponse(ctx context.Context, re GetHealthReadyWithResponse request returning \*GetHealthReadyResponse -### func \(\*ClientWithResponses\) [GetHealthStatusWithResponse]() +### func \(\*ClientWithResponses\) [GetHealthStatusWithResponse]() ```go func (c *ClientWithResponses) GetHealthStatusWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetHealthStatusResponse, error) @@ -1334,7 +1431,7 @@ func (c *ClientWithResponses) GetHealthStatusWithResponse(ctx context.Context, r GetHealthStatusWithResponse request returning \*GetHealthStatusResponse -### func \(\*ClientWithResponses\) [GetHealthWithResponse]() +### func \(\*ClientWithResponses\) [GetHealthWithResponse]() ```go func (c *ClientWithResponses) GetHealthWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetHealthResponse, error) @@ -1343,7 +1440,7 @@ func (c *ClientWithResponses) GetHealthWithResponse(ctx context.Context, reqEdit GetHealthWithResponse request returning \*GetHealthResponse -### func \(\*ClientWithResponses\) [GetJobByIDWithResponse]() +### func \(\*ClientWithResponses\) [GetJobByIDWithResponse]() ```go func (c *ClientWithResponses) GetJobByIDWithResponse(ctx context.Context, id openapi_types.UUID, reqEditors ...RequestEditorFn) (*GetJobByIDResponse, error) @@ -1352,7 +1449,7 @@ func (c *ClientWithResponses) GetJobByIDWithResponse(ctx context.Context, id ope GetJobByIDWithResponse request returning \*GetJobByIDResponse -### func \(\*ClientWithResponses\) [GetJobStatusWithResponse]() +### func \(\*ClientWithResponses\) [GetJobStatusWithResponse]() ```go func (c *ClientWithResponses) GetJobStatusWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetJobStatusResponse, error) @@ -1361,7 +1458,7 @@ func (c *ClientWithResponses) GetJobStatusWithResponse(ctx context.Context, reqE GetJobStatusWithResponse request returning \*GetJobStatusResponse -### func \(\*ClientWithResponses\) [GetJobWithResponse]() +### func \(\*ClientWithResponses\) [GetJobWithResponse]() ```go func (c *ClientWithResponses) GetJobWithResponse(ctx context.Context, params *GetJobParams, reqEditors ...RequestEditorFn) (*GetJobResponse, error) @@ -1370,7 +1467,7 @@ func (c *ClientWithResponses) GetJobWithResponse(ctx context.Context, params *Ge GetJobWithResponse request returning \*GetJobResponse -### func \(\*ClientWithResponses\) [GetNodeDiskWithResponse]() +### func \(\*ClientWithResponses\) [GetNodeDiskWithResponse]() ```go func (c *ClientWithResponses) GetNodeDiskWithResponse(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*GetNodeDiskResponse, error) @@ -1379,7 +1476,7 @@ func (c *ClientWithResponses) GetNodeDiskWithResponse(ctx context.Context, hostn GetNodeDiskWithResponse request returning \*GetNodeDiskResponse -### func \(\*ClientWithResponses\) [GetNodeHostnameWithResponse]() +### func \(\*ClientWithResponses\) [GetNodeHostnameWithResponse]() ```go func (c *ClientWithResponses) GetNodeHostnameWithResponse(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*GetNodeHostnameResponse, error) @@ -1388,7 +1485,7 @@ func (c *ClientWithResponses) GetNodeHostnameWithResponse(ctx context.Context, h GetNodeHostnameWithResponse request returning \*GetNodeHostnameResponse -### func \(\*ClientWithResponses\) [GetNodeLoadWithResponse]() +### func \(\*ClientWithResponses\) [GetNodeLoadWithResponse]() ```go func (c *ClientWithResponses) GetNodeLoadWithResponse(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*GetNodeLoadResponse, error) @@ -1397,7 +1494,7 @@ func (c *ClientWithResponses) GetNodeLoadWithResponse(ctx context.Context, hostn GetNodeLoadWithResponse request returning \*GetNodeLoadResponse -### func \(\*ClientWithResponses\) [GetNodeMemoryWithResponse]() +### func \(\*ClientWithResponses\) [GetNodeMemoryWithResponse]() ```go func (c *ClientWithResponses) GetNodeMemoryWithResponse(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*GetNodeMemoryResponse, error) @@ -1406,7 +1503,7 @@ func (c *ClientWithResponses) GetNodeMemoryWithResponse(ctx context.Context, hos GetNodeMemoryWithResponse request returning \*GetNodeMemoryResponse -### func \(\*ClientWithResponses\) [GetNodeNetworkDNSByInterfaceWithResponse]() +### func \(\*ClientWithResponses\) [GetNodeNetworkDNSByInterfaceWithResponse]() ```go func (c *ClientWithResponses) GetNodeNetworkDNSByInterfaceWithResponse(ctx context.Context, hostname Hostname, interfaceName string, reqEditors ...RequestEditorFn) (*GetNodeNetworkDNSByInterfaceResponse, error) @@ -1415,7 +1512,7 @@ func (c *ClientWithResponses) GetNodeNetworkDNSByInterfaceWithResponse(ctx conte GetNodeNetworkDNSByInterfaceWithResponse request returning \*GetNodeNetworkDNSByInterfaceResponse -### func \(\*ClientWithResponses\) [GetNodeOSWithResponse]() +### func \(\*ClientWithResponses\) [GetNodeOSWithResponse]() ```go func (c *ClientWithResponses) GetNodeOSWithResponse(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*GetNodeOSResponse, error) @@ -1424,7 +1521,7 @@ func (c *ClientWithResponses) GetNodeOSWithResponse(ctx context.Context, hostnam GetNodeOSWithResponse request returning \*GetNodeOSResponse -### func \(\*ClientWithResponses\) [GetNodeStatusWithResponse]() +### func \(\*ClientWithResponses\) [GetNodeStatusWithResponse]() ```go func (c *ClientWithResponses) GetNodeStatusWithResponse(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*GetNodeStatusResponse, error) @@ -1433,7 +1530,7 @@ func (c *ClientWithResponses) GetNodeStatusWithResponse(ctx context.Context, hos GetNodeStatusWithResponse request returning \*GetNodeStatusResponse -### func \(\*ClientWithResponses\) [GetNodeUptimeWithResponse]() +### func \(\*ClientWithResponses\) [GetNodeUptimeWithResponse]() ```go func (c *ClientWithResponses) GetNodeUptimeWithResponse(ctx context.Context, hostname Hostname, reqEditors ...RequestEditorFn) (*GetNodeUptimeResponse, error) @@ -1442,7 +1539,7 @@ func (c *ClientWithResponses) GetNodeUptimeWithResponse(ctx context.Context, hos GetNodeUptimeWithResponse request returning \*GetNodeUptimeResponse -### func \(\*ClientWithResponses\) [GetVersionWithResponse]() +### func \(\*ClientWithResponses\) [GetVersionWithResponse]() ```go func (c *ClientWithResponses) GetVersionWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetVersionResponse, error) @@ -1451,7 +1548,7 @@ func (c *ClientWithResponses) GetVersionWithResponse(ctx context.Context, reqEdi GetVersionWithResponse request returning \*GetVersionResponse -### func \(\*ClientWithResponses\) [PostJobWithBodyWithResponse]() +### func \(\*ClientWithResponses\) [PostJobWithBodyWithResponse]() ```go func (c *ClientWithResponses) PostJobWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostJobResponse, error) @@ -1460,7 +1557,7 @@ func (c *ClientWithResponses) PostJobWithBodyWithResponse(ctx context.Context, c PostJobWithBodyWithResponse request with arbitrary body returning \*PostJobResponse -### func \(\*ClientWithResponses\) [PostJobWithResponse]() +### func \(\*ClientWithResponses\) [PostJobWithResponse]() ```go func (c *ClientWithResponses) PostJobWithResponse(ctx context.Context, body PostJobJSONRequestBody, reqEditors ...RequestEditorFn) (*PostJobResponse, error) @@ -1469,7 +1566,7 @@ func (c *ClientWithResponses) PostJobWithResponse(ctx context.Context, body Post -### func \(\*ClientWithResponses\) [PostNodeCommandExecWithBodyWithResponse]() +### func \(\*ClientWithResponses\) [PostNodeCommandExecWithBodyWithResponse]() ```go func (c *ClientWithResponses) PostNodeCommandExecWithBodyWithResponse(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostNodeCommandExecResponse, error) @@ -1478,7 +1575,7 @@ func (c *ClientWithResponses) PostNodeCommandExecWithBodyWithResponse(ctx contex PostNodeCommandExecWithBodyWithResponse request with arbitrary body returning \*PostNodeCommandExecResponse -### func \(\*ClientWithResponses\) [PostNodeCommandExecWithResponse]() +### func \(\*ClientWithResponses\) [PostNodeCommandExecWithResponse]() ```go func (c *ClientWithResponses) PostNodeCommandExecWithResponse(ctx context.Context, hostname Hostname, body PostNodeCommandExecJSONRequestBody, reqEditors ...RequestEditorFn) (*PostNodeCommandExecResponse, error) @@ -1487,7 +1584,7 @@ func (c *ClientWithResponses) PostNodeCommandExecWithResponse(ctx context.Contex -### func \(\*ClientWithResponses\) [PostNodeCommandShellWithBodyWithResponse]() +### func \(\*ClientWithResponses\) [PostNodeCommandShellWithBodyWithResponse]() ```go func (c *ClientWithResponses) PostNodeCommandShellWithBodyWithResponse(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostNodeCommandShellResponse, error) @@ -1496,7 +1593,7 @@ func (c *ClientWithResponses) PostNodeCommandShellWithBodyWithResponse(ctx conte PostNodeCommandShellWithBodyWithResponse request with arbitrary body returning \*PostNodeCommandShellResponse -### func \(\*ClientWithResponses\) [PostNodeCommandShellWithResponse]() +### func \(\*ClientWithResponses\) [PostNodeCommandShellWithResponse]() ```go func (c *ClientWithResponses) PostNodeCommandShellWithResponse(ctx context.Context, hostname Hostname, body PostNodeCommandShellJSONRequestBody, reqEditors ...RequestEditorFn) (*PostNodeCommandShellResponse, error) @@ -1505,7 +1602,7 @@ func (c *ClientWithResponses) PostNodeCommandShellWithResponse(ctx context.Conte -### func \(\*ClientWithResponses\) [PostNodeNetworkPingWithBodyWithResponse]() +### func \(\*ClientWithResponses\) [PostNodeNetworkPingWithBodyWithResponse]() ```go func (c *ClientWithResponses) PostNodeNetworkPingWithBodyWithResponse(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostNodeNetworkPingResponse, error) @@ -1514,7 +1611,7 @@ func (c *ClientWithResponses) PostNodeNetworkPingWithBodyWithResponse(ctx contex PostNodeNetworkPingWithBodyWithResponse request with arbitrary body returning \*PostNodeNetworkPingResponse -### func \(\*ClientWithResponses\) [PostNodeNetworkPingWithResponse]() +### func \(\*ClientWithResponses\) [PostNodeNetworkPingWithResponse]() ```go func (c *ClientWithResponses) PostNodeNetworkPingWithResponse(ctx context.Context, hostname Hostname, body PostNodeNetworkPingJSONRequestBody, reqEditors ...RequestEditorFn) (*PostNodeNetworkPingResponse, error) @@ -1523,7 +1620,7 @@ func (c *ClientWithResponses) PostNodeNetworkPingWithResponse(ctx context.Contex -### func \(\*ClientWithResponses\) [PutNodeNetworkDNSWithBodyWithResponse]() +### func \(\*ClientWithResponses\) [PutNodeNetworkDNSWithBodyWithResponse]() ```go func (c *ClientWithResponses) PutNodeNetworkDNSWithBodyWithResponse(ctx context.Context, hostname Hostname, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PutNodeNetworkDNSResponse, error) @@ -1532,7 +1629,7 @@ func (c *ClientWithResponses) PutNodeNetworkDNSWithBodyWithResponse(ctx context. PutNodeNetworkDNSWithBodyWithResponse request with arbitrary body returning \*PutNodeNetworkDNSResponse -### func \(\*ClientWithResponses\) [PutNodeNetworkDNSWithResponse]() +### func \(\*ClientWithResponses\) [PutNodeNetworkDNSWithResponse]() ```go func (c *ClientWithResponses) PutNodeNetworkDNSWithResponse(ctx context.Context, hostname Hostname, body PutNodeNetworkDNSJSONRequestBody, reqEditors ...RequestEditorFn) (*PutNodeNetworkDNSResponse, error) @@ -1541,7 +1638,7 @@ func (c *ClientWithResponses) PutNodeNetworkDNSWithResponse(ctx context.Context, -### func \(\*ClientWithResponses\) [RetryJobByIDWithBodyWithResponse]() +### func \(\*ClientWithResponses\) [RetryJobByIDWithBodyWithResponse]() ```go func (c *ClientWithResponses) RetryJobByIDWithBodyWithResponse(ctx context.Context, id openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RetryJobByIDResponse, error) @@ -1550,7 +1647,7 @@ func (c *ClientWithResponses) RetryJobByIDWithBodyWithResponse(ctx context.Conte RetryJobByIDWithBodyWithResponse request with arbitrary body returning \*RetryJobByIDResponse -### func \(\*ClientWithResponses\) [RetryJobByIDWithResponse]() +### func \(\*ClientWithResponses\) [RetryJobByIDWithResponse]() ```go func (c *ClientWithResponses) RetryJobByIDWithResponse(ctx context.Context, id openapi_types.UUID, body RetryJobByIDJSONRequestBody, reqEditors ...RequestEditorFn) (*RetryJobByIDResponse, error) @@ -1558,8 +1655,17 @@ func (c *ClientWithResponses) RetryJobByIDWithResponse(ctx context.Context, id o + +### func \(\*ClientWithResponses\) [UndrainAgentWithResponse]() + +```go +func (c *ClientWithResponses) UndrainAgentWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*UndrainAgentResponse, error) +``` + +UndrainAgentWithResponse request returning \*UndrainAgentResponse + -## type [ClientWithResponsesInterface]() +## type [ClientWithResponsesInterface]() ClientWithResponsesInterface is the interface specification for the client with responses above. @@ -1571,6 +1677,12 @@ type ClientWithResponsesInterface interface { // GetAgentDetailsWithResponse request GetAgentDetailsWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*GetAgentDetailsResponse, error) + // DrainAgentWithResponse request + DrainAgentWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*DrainAgentResponse, error) + + // UndrainAgentWithResponse request + UndrainAgentWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*UndrainAgentResponse, error) + // GetAuditLogsWithResponse request GetAuditLogsWithResponse(ctx context.Context, params *GetAuditLogsParams, reqEditors ...RequestEditorFn) (*GetAuditLogsResponse, error) @@ -1661,7 +1773,7 @@ type ClientWithResponsesInterface interface { ``` -## type [CommandExecRequest]() +## type [CommandExecRequest]() CommandExecRequest defines model for CommandExecRequest. @@ -1682,7 +1794,7 @@ type CommandExecRequest struct { ``` -## type [CommandResultCollectionResponse]() +## type [CommandResultCollectionResponse]() CommandResultCollectionResponse defines model for CommandResultCollectionResponse. @@ -1695,7 +1807,7 @@ type CommandResultCollectionResponse struct { ``` -## type [CommandResultItem]() +## type [CommandResultItem]() CommandResultItem defines model for CommandResultItem. @@ -1725,7 +1837,7 @@ type CommandResultItem struct { ``` -## type [CommandShellRequest]() +## type [CommandShellRequest]() CommandShellRequest defines model for CommandShellRequest. @@ -1743,7 +1855,7 @@ type CommandShellRequest struct { ``` -## type [ComponentHealth]() +## type [ComponentHealth]() ComponentHealth defines model for ComponentHealth. @@ -1758,7 +1870,7 @@ type ComponentHealth struct { ``` -## type [ConsumerDetail]() +## type [ConsumerDetail]() ConsumerDetail defines model for ConsumerDetail. @@ -1779,7 +1891,7 @@ type ConsumerDetail struct { ``` -## type [ConsumerStats]() +## type [ConsumerStats]() ConsumerStats defines model for ConsumerStats. @@ -1794,7 +1906,7 @@ type ConsumerStats struct { ``` -## type [CreateJobRequest]() +## type [CreateJobRequest]() CreateJobRequest defines model for CreateJobRequest. @@ -1809,7 +1921,7 @@ type CreateJobRequest struct { ``` -## type [CreateJobResponse]() +## type [CreateJobResponse]() CreateJobResponse defines model for CreateJobResponse. @@ -1830,7 +1942,7 @@ type CreateJobResponse struct { ``` -## type [DNSConfigCollectionResponse]() +## type [DNSConfigCollectionResponse]() DNSConfigCollectionResponse defines model for DNSConfigCollectionResponse. @@ -1843,7 +1955,7 @@ type DNSConfigCollectionResponse struct { ``` -## type [DNSConfigResponse]() +## type [DNSConfigResponse]() DNSConfigResponse defines model for DNSConfigResponse. @@ -1864,7 +1976,7 @@ type DNSConfigResponse struct { ``` -## type [DNSConfigUpdateRequest]() +## type [DNSConfigUpdateRequest]() DNSConfigUpdateRequest defines model for DNSConfigUpdateRequest. @@ -1882,7 +1994,7 @@ type DNSConfigUpdateRequest struct { ``` -## type [DNSUpdateCollectionResponse]() +## type [DNSUpdateCollectionResponse]() DNSUpdateCollectionResponse defines model for DNSUpdateCollectionResponse. @@ -1895,7 +2007,7 @@ type DNSUpdateCollectionResponse struct { ``` -## type [DNSUpdateResultItem]() +## type [DNSUpdateResultItem]() DNSUpdateResultItem defines model for DNSUpdateResultItem. @@ -1910,7 +2022,7 @@ type DNSUpdateResultItem struct { ``` -## type [DNSUpdateResultItemStatus]() +## type [DNSUpdateResultItemStatus]() DNSUpdateResultItemStatus defines model for DNSUpdateResultItem.Status. @@ -1928,7 +2040,7 @@ const ( ``` -## type [DeleteJobByIDResponse]() +## type [DeleteJobByIDResponse]() @@ -1945,7 +2057,7 @@ type DeleteJobByIDResponse struct { ``` -### func [ParseDeleteJobByIDResponse]() +### func [ParseDeleteJobByIDResponse]() ```go func ParseDeleteJobByIDResponse(rsp *http.Response) (*DeleteJobByIDResponse, error) @@ -1954,7 +2066,7 @@ func ParseDeleteJobByIDResponse(rsp *http.Response) (*DeleteJobByIDResponse, err ParseDeleteJobByIDResponse parses an HTTP response from a DeleteJobByIDWithResponse call -### func \(DeleteJobByIDResponse\) [Status]() +### func \(DeleteJobByIDResponse\) [Status]() ```go func (r DeleteJobByIDResponse) Status() string @@ -1963,7 +2075,7 @@ func (r DeleteJobByIDResponse) Status() string Status returns HTTPResponse.Status -### func \(DeleteJobByIDResponse\) [StatusCode]() +### func \(DeleteJobByIDResponse\) [StatusCode]() ```go func (r DeleteJobByIDResponse) StatusCode() int @@ -1972,7 +2084,7 @@ func (r DeleteJobByIDResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [DiskCollectionResponse]() +## type [DiskCollectionResponse]() DiskCollectionResponse defines model for DiskCollectionResponse. @@ -1985,7 +2097,7 @@ type DiskCollectionResponse struct { ``` -## type [DiskResponse]() +## type [DiskResponse]() DiskResponse Local disk usage information. @@ -2006,7 +2118,7 @@ type DiskResponse struct { ``` -## type [DiskResultItem]() +## type [DiskResultItem]() DiskResultItem defines model for DiskResultItem. @@ -2024,7 +2136,7 @@ type DiskResultItem struct { ``` -## type [DisksResponse]() +## type [DisksResponse]() DisksResponse List of local disk usage information. @@ -2032,8 +2144,54 @@ DisksResponse List of local disk usage information. type DisksResponse = []DiskResponse ``` + +## type [DrainAgentResponse]() + + + +```go +type DrainAgentResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Message string `json:"message"` + } + JSON401 *ErrorResponse + JSON403 *ErrorResponse + JSON404 *ErrorResponse + JSON409 *ErrorResponse +} +``` + + +### func [ParseDrainAgentResponse]() + +```go +func ParseDrainAgentResponse(rsp *http.Response) (*DrainAgentResponse, error) +``` + +ParseDrainAgentResponse parses an HTTP response from a DrainAgentWithResponse call + + +### func \(DrainAgentResponse\) [Status]() + +```go +func (r DrainAgentResponse) Status() string +``` + +Status returns HTTPResponse.Status + + +### func \(DrainAgentResponse\) [StatusCode]() + +```go +func (r DrainAgentResponse) StatusCode() int +``` + +StatusCode returns HTTPResponse.StatusCode + -## type [ErrorResponse]() +## type [ErrorResponse]() ErrorResponse defines model for ErrorResponse. @@ -2051,7 +2209,7 @@ type ErrorResponse struct { ``` -## type [GetAgentDetailsResponse]() +## type [GetAgentDetailsResponse]() @@ -2068,7 +2226,7 @@ type GetAgentDetailsResponse struct { ``` -### func [ParseGetAgentDetailsResponse]() +### func [ParseGetAgentDetailsResponse]() ```go func ParseGetAgentDetailsResponse(rsp *http.Response) (*GetAgentDetailsResponse, error) @@ -2077,7 +2235,7 @@ func ParseGetAgentDetailsResponse(rsp *http.Response) (*GetAgentDetailsResponse, ParseGetAgentDetailsResponse parses an HTTP response from a GetAgentDetailsWithResponse call -### func \(GetAgentDetailsResponse\) [Status]() +### func \(GetAgentDetailsResponse\) [Status]() ```go func (r GetAgentDetailsResponse) Status() string @@ -2086,7 +2244,7 @@ func (r GetAgentDetailsResponse) Status() string Status returns HTTPResponse.Status -### func \(GetAgentDetailsResponse\) [StatusCode]() +### func \(GetAgentDetailsResponse\) [StatusCode]() ```go func (r GetAgentDetailsResponse) StatusCode() int @@ -2095,7 +2253,7 @@ func (r GetAgentDetailsResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetAgentResponse]() +## type [GetAgentResponse]() @@ -2111,7 +2269,7 @@ type GetAgentResponse struct { ``` -### func [ParseGetAgentResponse]() +### func [ParseGetAgentResponse]() ```go func ParseGetAgentResponse(rsp *http.Response) (*GetAgentResponse, error) @@ -2120,7 +2278,7 @@ func ParseGetAgentResponse(rsp *http.Response) (*GetAgentResponse, error) ParseGetAgentResponse parses an HTTP response from a GetAgentWithResponse call -### func \(GetAgentResponse\) [Status]() +### func \(GetAgentResponse\) [Status]() ```go func (r GetAgentResponse) Status() string @@ -2129,7 +2287,7 @@ func (r GetAgentResponse) Status() string Status returns HTTPResponse.Status -### func \(GetAgentResponse\) [StatusCode]() +### func \(GetAgentResponse\) [StatusCode]() ```go func (r GetAgentResponse) StatusCode() int @@ -2138,7 +2296,7 @@ func (r GetAgentResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetAuditExportResponse]() +## type [GetAuditExportResponse]() @@ -2154,7 +2312,7 @@ type GetAuditExportResponse struct { ``` -### func [ParseGetAuditExportResponse]() +### func [ParseGetAuditExportResponse]() ```go func ParseGetAuditExportResponse(rsp *http.Response) (*GetAuditExportResponse, error) @@ -2163,7 +2321,7 @@ func ParseGetAuditExportResponse(rsp *http.Response) (*GetAuditExportResponse, e ParseGetAuditExportResponse parses an HTTP response from a GetAuditExportWithResponse call -### func \(GetAuditExportResponse\) [Status]() +### func \(GetAuditExportResponse\) [Status]() ```go func (r GetAuditExportResponse) Status() string @@ -2172,7 +2330,7 @@ func (r GetAuditExportResponse) Status() string Status returns HTTPResponse.Status -### func \(GetAuditExportResponse\) [StatusCode]() +### func \(GetAuditExportResponse\) [StatusCode]() ```go func (r GetAuditExportResponse) StatusCode() int @@ -2181,7 +2339,7 @@ func (r GetAuditExportResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetAuditLogByIDResponse]() +## type [GetAuditLogByIDResponse]() @@ -2198,7 +2356,7 @@ type GetAuditLogByIDResponse struct { ``` -### func [ParseGetAuditLogByIDResponse]() +### func [ParseGetAuditLogByIDResponse]() ```go func ParseGetAuditLogByIDResponse(rsp *http.Response) (*GetAuditLogByIDResponse, error) @@ -2207,7 +2365,7 @@ func ParseGetAuditLogByIDResponse(rsp *http.Response) (*GetAuditLogByIDResponse, ParseGetAuditLogByIDResponse parses an HTTP response from a GetAuditLogByIDWithResponse call -### func \(GetAuditLogByIDResponse\) [Status]() +### func \(GetAuditLogByIDResponse\) [Status]() ```go func (r GetAuditLogByIDResponse) Status() string @@ -2216,7 +2374,7 @@ func (r GetAuditLogByIDResponse) Status() string Status returns HTTPResponse.Status -### func \(GetAuditLogByIDResponse\) [StatusCode]() +### func \(GetAuditLogByIDResponse\) [StatusCode]() ```go func (r GetAuditLogByIDResponse) StatusCode() int @@ -2225,7 +2383,7 @@ func (r GetAuditLogByIDResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetAuditLogsParams]() +## type [GetAuditLogsParams]() GetAuditLogsParams defines parameters for GetAuditLogs. @@ -2240,7 +2398,7 @@ type GetAuditLogsParams struct { ``` -## type [GetAuditLogsResponse]() +## type [GetAuditLogsResponse]() @@ -2257,7 +2415,7 @@ type GetAuditLogsResponse struct { ``` -### func [ParseGetAuditLogsResponse]() +### func [ParseGetAuditLogsResponse]() ```go func ParseGetAuditLogsResponse(rsp *http.Response) (*GetAuditLogsResponse, error) @@ -2266,7 +2424,7 @@ func ParseGetAuditLogsResponse(rsp *http.Response) (*GetAuditLogsResponse, error ParseGetAuditLogsResponse parses an HTTP response from a GetAuditLogsWithResponse call -### func \(GetAuditLogsResponse\) [Status]() +### func \(GetAuditLogsResponse\) [Status]() ```go func (r GetAuditLogsResponse) Status() string @@ -2275,7 +2433,7 @@ func (r GetAuditLogsResponse) Status() string Status returns HTTPResponse.Status -### func \(GetAuditLogsResponse\) [StatusCode]() +### func \(GetAuditLogsResponse\) [StatusCode]() ```go func (r GetAuditLogsResponse) StatusCode() int @@ -2284,7 +2442,7 @@ func (r GetAuditLogsResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetHealthReadyResponse]() +## type [GetHealthReadyResponse]() @@ -2298,7 +2456,7 @@ type GetHealthReadyResponse struct { ``` -### func [ParseGetHealthReadyResponse]() +### func [ParseGetHealthReadyResponse]() ```go func ParseGetHealthReadyResponse(rsp *http.Response) (*GetHealthReadyResponse, error) @@ -2307,7 +2465,7 @@ func ParseGetHealthReadyResponse(rsp *http.Response) (*GetHealthReadyResponse, e ParseGetHealthReadyResponse parses an HTTP response from a GetHealthReadyWithResponse call -### func \(GetHealthReadyResponse\) [Status]() +### func \(GetHealthReadyResponse\) [Status]() ```go func (r GetHealthReadyResponse) Status() string @@ -2316,7 +2474,7 @@ func (r GetHealthReadyResponse) Status() string Status returns HTTPResponse.Status -### func \(GetHealthReadyResponse\) [StatusCode]() +### func \(GetHealthReadyResponse\) [StatusCode]() ```go func (r GetHealthReadyResponse) StatusCode() int @@ -2325,7 +2483,7 @@ func (r GetHealthReadyResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetHealthResponse]() +## type [GetHealthResponse]() @@ -2338,7 +2496,7 @@ type GetHealthResponse struct { ``` -### func [ParseGetHealthResponse]() +### func [ParseGetHealthResponse]() ```go func ParseGetHealthResponse(rsp *http.Response) (*GetHealthResponse, error) @@ -2347,7 +2505,7 @@ func ParseGetHealthResponse(rsp *http.Response) (*GetHealthResponse, error) ParseGetHealthResponse parses an HTTP response from a GetHealthWithResponse call -### func \(GetHealthResponse\) [Status]() +### func \(GetHealthResponse\) [Status]() ```go func (r GetHealthResponse) Status() string @@ -2356,7 +2514,7 @@ func (r GetHealthResponse) Status() string Status returns HTTPResponse.Status -### func \(GetHealthResponse\) [StatusCode]() +### func \(GetHealthResponse\) [StatusCode]() ```go func (r GetHealthResponse) StatusCode() int @@ -2365,7 +2523,7 @@ func (r GetHealthResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetHealthStatusResponse]() +## type [GetHealthStatusResponse]() @@ -2381,7 +2539,7 @@ type GetHealthStatusResponse struct { ``` -### func [ParseGetHealthStatusResponse]() +### func [ParseGetHealthStatusResponse]() ```go func ParseGetHealthStatusResponse(rsp *http.Response) (*GetHealthStatusResponse, error) @@ -2390,7 +2548,7 @@ func ParseGetHealthStatusResponse(rsp *http.Response) (*GetHealthStatusResponse, ParseGetHealthStatusResponse parses an HTTP response from a GetHealthStatusWithResponse call -### func \(GetHealthStatusResponse\) [Status]() +### func \(GetHealthStatusResponse\) [Status]() ```go func (r GetHealthStatusResponse) Status() string @@ -2399,7 +2557,7 @@ func (r GetHealthStatusResponse) Status() string Status returns HTTPResponse.Status -### func \(GetHealthStatusResponse\) [StatusCode]() +### func \(GetHealthStatusResponse\) [StatusCode]() ```go func (r GetHealthStatusResponse) StatusCode() int @@ -2408,7 +2566,7 @@ func (r GetHealthStatusResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetJobByIDResponse]() +## type [GetJobByIDResponse]() @@ -2426,7 +2584,7 @@ type GetJobByIDResponse struct { ``` -### func [ParseGetJobByIDResponse]() +### func [ParseGetJobByIDResponse]() ```go func ParseGetJobByIDResponse(rsp *http.Response) (*GetJobByIDResponse, error) @@ -2435,7 +2593,7 @@ func ParseGetJobByIDResponse(rsp *http.Response) (*GetJobByIDResponse, error) ParseGetJobByIDResponse parses an HTTP response from a GetJobByIDWithResponse call -### func \(GetJobByIDResponse\) [Status]() +### func \(GetJobByIDResponse\) [Status]() ```go func (r GetJobByIDResponse) Status() string @@ -2444,7 +2602,7 @@ func (r GetJobByIDResponse) Status() string Status returns HTTPResponse.Status -### func \(GetJobByIDResponse\) [StatusCode]() +### func \(GetJobByIDResponse\) [StatusCode]() ```go func (r GetJobByIDResponse) StatusCode() int @@ -2453,7 +2611,7 @@ func (r GetJobByIDResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetJobParams]() +## type [GetJobParams]() GetJobParams defines parameters for GetJob. @@ -2471,7 +2629,7 @@ type GetJobParams struct { ``` -## type [GetJobParamsStatus]() +## type [GetJobParamsStatus]() GetJobParamsStatus defines parameters for GetJob. @@ -2492,7 +2650,7 @@ const ( ``` -## type [GetJobResponse]() +## type [GetJobResponse]() @@ -2509,7 +2667,7 @@ type GetJobResponse struct { ``` -### func [ParseGetJobResponse]() +### func [ParseGetJobResponse]() ```go func ParseGetJobResponse(rsp *http.Response) (*GetJobResponse, error) @@ -2518,7 +2676,7 @@ func ParseGetJobResponse(rsp *http.Response) (*GetJobResponse, error) ParseGetJobResponse parses an HTTP response from a GetJobWithResponse call -### func \(GetJobResponse\) [Status]() +### func \(GetJobResponse\) [Status]() ```go func (r GetJobResponse) Status() string @@ -2527,7 +2685,7 @@ func (r GetJobResponse) Status() string Status returns HTTPResponse.Status -### func \(GetJobResponse\) [StatusCode]() +### func \(GetJobResponse\) [StatusCode]() ```go func (r GetJobResponse) StatusCode() int @@ -2536,7 +2694,7 @@ func (r GetJobResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetJobStatusResponse]() +## type [GetJobStatusResponse]() @@ -2552,7 +2710,7 @@ type GetJobStatusResponse struct { ``` -### func [ParseGetJobStatusResponse]() +### func [ParseGetJobStatusResponse]() ```go func ParseGetJobStatusResponse(rsp *http.Response) (*GetJobStatusResponse, error) @@ -2561,7 +2719,7 @@ func ParseGetJobStatusResponse(rsp *http.Response) (*GetJobStatusResponse, error ParseGetJobStatusResponse parses an HTTP response from a GetJobStatusWithResponse call -### func \(GetJobStatusResponse\) [Status]() +### func \(GetJobStatusResponse\) [Status]() ```go func (r GetJobStatusResponse) Status() string @@ -2570,7 +2728,7 @@ func (r GetJobStatusResponse) Status() string Status returns HTTPResponse.Status -### func \(GetJobStatusResponse\) [StatusCode]() +### func \(GetJobStatusResponse\) [StatusCode]() ```go func (r GetJobStatusResponse) StatusCode() int @@ -2579,7 +2737,7 @@ func (r GetJobStatusResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetNodeDiskResponse]() +## type [GetNodeDiskResponse]() @@ -2596,7 +2754,7 @@ type GetNodeDiskResponse struct { ``` -### func [ParseGetNodeDiskResponse]() +### func [ParseGetNodeDiskResponse]() ```go func ParseGetNodeDiskResponse(rsp *http.Response) (*GetNodeDiskResponse, error) @@ -2605,7 +2763,7 @@ func ParseGetNodeDiskResponse(rsp *http.Response) (*GetNodeDiskResponse, error) ParseGetNodeDiskResponse parses an HTTP response from a GetNodeDiskWithResponse call -### func \(GetNodeDiskResponse\) [Status]() +### func \(GetNodeDiskResponse\) [Status]() ```go func (r GetNodeDiskResponse) Status() string @@ -2614,7 +2772,7 @@ func (r GetNodeDiskResponse) Status() string Status returns HTTPResponse.Status -### func \(GetNodeDiskResponse\) [StatusCode]() +### func \(GetNodeDiskResponse\) [StatusCode]() ```go func (r GetNodeDiskResponse) StatusCode() int @@ -2623,7 +2781,7 @@ func (r GetNodeDiskResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetNodeHostnameResponse]() +## type [GetNodeHostnameResponse]() @@ -2640,7 +2798,7 @@ type GetNodeHostnameResponse struct { ``` -### func [ParseGetNodeHostnameResponse]() +### func [ParseGetNodeHostnameResponse]() ```go func ParseGetNodeHostnameResponse(rsp *http.Response) (*GetNodeHostnameResponse, error) @@ -2649,7 +2807,7 @@ func ParseGetNodeHostnameResponse(rsp *http.Response) (*GetNodeHostnameResponse, ParseGetNodeHostnameResponse parses an HTTP response from a GetNodeHostnameWithResponse call -### func \(GetNodeHostnameResponse\) [Status]() +### func \(GetNodeHostnameResponse\) [Status]() ```go func (r GetNodeHostnameResponse) Status() string @@ -2658,7 +2816,7 @@ func (r GetNodeHostnameResponse) Status() string Status returns HTTPResponse.Status -### func \(GetNodeHostnameResponse\) [StatusCode]() +### func \(GetNodeHostnameResponse\) [StatusCode]() ```go func (r GetNodeHostnameResponse) StatusCode() int @@ -2667,7 +2825,7 @@ func (r GetNodeHostnameResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetNodeLoadResponse]() +## type [GetNodeLoadResponse]() @@ -2684,7 +2842,7 @@ type GetNodeLoadResponse struct { ``` -### func [ParseGetNodeLoadResponse]() +### func [ParseGetNodeLoadResponse]() ```go func ParseGetNodeLoadResponse(rsp *http.Response) (*GetNodeLoadResponse, error) @@ -2693,7 +2851,7 @@ func ParseGetNodeLoadResponse(rsp *http.Response) (*GetNodeLoadResponse, error) ParseGetNodeLoadResponse parses an HTTP response from a GetNodeLoadWithResponse call -### func \(GetNodeLoadResponse\) [Status]() +### func \(GetNodeLoadResponse\) [Status]() ```go func (r GetNodeLoadResponse) Status() string @@ -2702,7 +2860,7 @@ func (r GetNodeLoadResponse) Status() string Status returns HTTPResponse.Status -### func \(GetNodeLoadResponse\) [StatusCode]() +### func \(GetNodeLoadResponse\) [StatusCode]() ```go func (r GetNodeLoadResponse) StatusCode() int @@ -2711,7 +2869,7 @@ func (r GetNodeLoadResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetNodeMemoryResponse]() +## type [GetNodeMemoryResponse]() @@ -2728,7 +2886,7 @@ type GetNodeMemoryResponse struct { ``` -### func [ParseGetNodeMemoryResponse]() +### func [ParseGetNodeMemoryResponse]() ```go func ParseGetNodeMemoryResponse(rsp *http.Response) (*GetNodeMemoryResponse, error) @@ -2737,7 +2895,7 @@ func ParseGetNodeMemoryResponse(rsp *http.Response) (*GetNodeMemoryResponse, err ParseGetNodeMemoryResponse parses an HTTP response from a GetNodeMemoryWithResponse call -### func \(GetNodeMemoryResponse\) [Status]() +### func \(GetNodeMemoryResponse\) [Status]() ```go func (r GetNodeMemoryResponse) Status() string @@ -2746,7 +2904,7 @@ func (r GetNodeMemoryResponse) Status() string Status returns HTTPResponse.Status -### func \(GetNodeMemoryResponse\) [StatusCode]() +### func \(GetNodeMemoryResponse\) [StatusCode]() ```go func (r GetNodeMemoryResponse) StatusCode() int @@ -2755,7 +2913,7 @@ func (r GetNodeMemoryResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetNodeNetworkDNSByInterfaceResponse]() +## type [GetNodeNetworkDNSByInterfaceResponse]() @@ -2772,7 +2930,7 @@ type GetNodeNetworkDNSByInterfaceResponse struct { ``` -### func [ParseGetNodeNetworkDNSByInterfaceResponse]() +### func [ParseGetNodeNetworkDNSByInterfaceResponse]() ```go func ParseGetNodeNetworkDNSByInterfaceResponse(rsp *http.Response) (*GetNodeNetworkDNSByInterfaceResponse, error) @@ -2781,7 +2939,7 @@ func ParseGetNodeNetworkDNSByInterfaceResponse(rsp *http.Response) (*GetNodeNetw ParseGetNodeNetworkDNSByInterfaceResponse parses an HTTP response from a GetNodeNetworkDNSByInterfaceWithResponse call -### func \(GetNodeNetworkDNSByInterfaceResponse\) [Status]() +### func \(GetNodeNetworkDNSByInterfaceResponse\) [Status]() ```go func (r GetNodeNetworkDNSByInterfaceResponse) Status() string @@ -2790,7 +2948,7 @@ func (r GetNodeNetworkDNSByInterfaceResponse) Status() string Status returns HTTPResponse.Status -### func \(GetNodeNetworkDNSByInterfaceResponse\) [StatusCode]() +### func \(GetNodeNetworkDNSByInterfaceResponse\) [StatusCode]() ```go func (r GetNodeNetworkDNSByInterfaceResponse) StatusCode() int @@ -2799,7 +2957,7 @@ func (r GetNodeNetworkDNSByInterfaceResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetNodeOSResponse]() +## type [GetNodeOSResponse]() @@ -2816,7 +2974,7 @@ type GetNodeOSResponse struct { ``` -### func [ParseGetNodeOSResponse]() +### func [ParseGetNodeOSResponse]() ```go func ParseGetNodeOSResponse(rsp *http.Response) (*GetNodeOSResponse, error) @@ -2825,7 +2983,7 @@ func ParseGetNodeOSResponse(rsp *http.Response) (*GetNodeOSResponse, error) ParseGetNodeOSResponse parses an HTTP response from a GetNodeOSWithResponse call -### func \(GetNodeOSResponse\) [Status]() +### func \(GetNodeOSResponse\) [Status]() ```go func (r GetNodeOSResponse) Status() string @@ -2834,7 +2992,7 @@ func (r GetNodeOSResponse) Status() string Status returns HTTPResponse.Status -### func \(GetNodeOSResponse\) [StatusCode]() +### func \(GetNodeOSResponse\) [StatusCode]() ```go func (r GetNodeOSResponse) StatusCode() int @@ -2843,7 +3001,7 @@ func (r GetNodeOSResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetNodeStatusResponse]() +## type [GetNodeStatusResponse]() @@ -2860,7 +3018,7 @@ type GetNodeStatusResponse struct { ``` -### func [ParseGetNodeStatusResponse]() +### func [ParseGetNodeStatusResponse]() ```go func ParseGetNodeStatusResponse(rsp *http.Response) (*GetNodeStatusResponse, error) @@ -2869,7 +3027,7 @@ func ParseGetNodeStatusResponse(rsp *http.Response) (*GetNodeStatusResponse, err ParseGetNodeStatusResponse parses an HTTP response from a GetNodeStatusWithResponse call -### func \(GetNodeStatusResponse\) [Status]() +### func \(GetNodeStatusResponse\) [Status]() ```go func (r GetNodeStatusResponse) Status() string @@ -2878,7 +3036,7 @@ func (r GetNodeStatusResponse) Status() string Status returns HTTPResponse.Status -### func \(GetNodeStatusResponse\) [StatusCode]() +### func \(GetNodeStatusResponse\) [StatusCode]() ```go func (r GetNodeStatusResponse) StatusCode() int @@ -2887,7 +3045,7 @@ func (r GetNodeStatusResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetNodeUptimeResponse]() +## type [GetNodeUptimeResponse]() @@ -2904,7 +3062,7 @@ type GetNodeUptimeResponse struct { ``` -### func [ParseGetNodeUptimeResponse]() +### func [ParseGetNodeUptimeResponse]() ```go func ParseGetNodeUptimeResponse(rsp *http.Response) (*GetNodeUptimeResponse, error) @@ -2913,7 +3071,7 @@ func ParseGetNodeUptimeResponse(rsp *http.Response) (*GetNodeUptimeResponse, err ParseGetNodeUptimeResponse parses an HTTP response from a GetNodeUptimeWithResponse call -### func \(GetNodeUptimeResponse\) [Status]() +### func \(GetNodeUptimeResponse\) [Status]() ```go func (r GetNodeUptimeResponse) Status() string @@ -2922,7 +3080,7 @@ func (r GetNodeUptimeResponse) Status() string Status returns HTTPResponse.Status -### func \(GetNodeUptimeResponse\) [StatusCode]() +### func \(GetNodeUptimeResponse\) [StatusCode]() ```go func (r GetNodeUptimeResponse) StatusCode() int @@ -2931,7 +3089,7 @@ func (r GetNodeUptimeResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [GetVersionResponse]() +## type [GetVersionResponse]() @@ -2944,7 +3102,7 @@ type GetVersionResponse struct { ``` -### func [ParseGetVersionResponse]() +### func [ParseGetVersionResponse]() ```go func ParseGetVersionResponse(rsp *http.Response) (*GetVersionResponse, error) @@ -2953,7 +3111,7 @@ func ParseGetVersionResponse(rsp *http.Response) (*GetVersionResponse, error) ParseGetVersionResponse parses an HTTP response from a GetVersionWithResponse call -### func \(GetVersionResponse\) [Status]() +### func \(GetVersionResponse\) [Status]() ```go func (r GetVersionResponse) Status() string @@ -2962,7 +3120,7 @@ func (r GetVersionResponse) Status() string Status returns HTTPResponse.Status -### func \(GetVersionResponse\) [StatusCode]() +### func \(GetVersionResponse\) [StatusCode]() ```go func (r GetVersionResponse) StatusCode() int @@ -2971,7 +3129,7 @@ func (r GetVersionResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [HealthResponse]() +## type [HealthResponse]() HealthResponse defines model for HealthResponse. @@ -2983,7 +3141,7 @@ type HealthResponse struct { ``` -## type [Hostname]() +## type [Hostname]() Hostname defines model for Hostname. @@ -2992,7 +3150,7 @@ type Hostname = string ``` -## type [HostnameCollectionResponse]() +## type [HostnameCollectionResponse]() HostnameCollectionResponse defines model for HostnameCollectionResponse. @@ -3005,7 +3163,7 @@ type HostnameCollectionResponse struct { ``` -## type [HostnameResponse]() +## type [HostnameResponse]() HostnameResponse The hostname of the system. @@ -3023,7 +3181,7 @@ type HostnameResponse struct { ``` -## type [HttpRequestDoer]() +## type [HttpRequestDoer]() Doer performs HTTP requests. @@ -3036,7 +3194,7 @@ type HttpRequestDoer interface { ``` -## type [JobDetailResponse]() +## type [JobDetailResponse]() JobDetailResponse defines model for JobDetailResponse. @@ -3103,7 +3261,7 @@ type JobDetailResponse struct { ``` -## type [JobStats]() +## type [JobStats]() JobStats defines model for JobStats. @@ -3130,7 +3288,7 @@ type JobStats struct { ``` -## type [KVBucketInfo]() +## type [KVBucketInfo]() KVBucketInfo defines model for KVBucketInfo. @@ -3148,7 +3306,7 @@ type KVBucketInfo struct { ``` -## type [ListAgentsResponse]() +## type [ListAgentsResponse]() ListAgentsResponse defines model for ListAgentsResponse. @@ -3162,7 +3320,7 @@ type ListAgentsResponse struct { ``` -## type [ListAuditResponse]() +## type [ListAuditResponse]() ListAuditResponse defines model for ListAuditResponse. @@ -3177,7 +3335,7 @@ type ListAuditResponse struct { ``` -## type [ListJobsResponse]() +## type [ListJobsResponse]() ListJobsResponse defines model for ListJobsResponse. @@ -3191,7 +3349,7 @@ type ListJobsResponse struct { ``` -## type [LoadAverageResponse]() +## type [LoadAverageResponse]() LoadAverageResponse The system load averages for 1, 5, and 15 minutes. @@ -3209,7 +3367,7 @@ type LoadAverageResponse struct { ``` -## type [LoadCollectionResponse]() +## type [LoadCollectionResponse]() LoadCollectionResponse defines model for LoadCollectionResponse. @@ -3222,7 +3380,7 @@ type LoadCollectionResponse struct { ``` -## type [LoadResultItem]() +## type [LoadResultItem]() LoadResultItem defines model for LoadResultItem. @@ -3240,7 +3398,7 @@ type LoadResultItem struct { ``` -## type [MemoryCollectionResponse]() +## type [MemoryCollectionResponse]() MemoryCollectionResponse defines model for MemoryCollectionResponse. @@ -3253,7 +3411,7 @@ type MemoryCollectionResponse struct { ``` -## type [MemoryResponse]() +## type [MemoryResponse]() MemoryResponse Memory usage information. @@ -3271,7 +3429,7 @@ type MemoryResponse struct { ``` -## type [MemoryResultItem]() +## type [MemoryResultItem]() MemoryResultItem defines model for MemoryResultItem. @@ -3289,7 +3447,7 @@ type MemoryResultItem struct { ``` -## type [NATSInfo]() +## type [NATSInfo]() NATSInfo defines model for NATSInfo. @@ -3304,7 +3462,7 @@ type NATSInfo struct { ``` -## type [NetworkInterfaceResponse]() +## type [NetworkInterfaceResponse]() NetworkInterfaceResponse defines model for NetworkInterfaceResponse. @@ -3320,7 +3478,7 @@ type NetworkInterfaceResponse struct { ``` -## type [NetworkInterfaceResponseFamily]() +## type [NetworkInterfaceResponseFamily]() NetworkInterfaceResponseFamily IP address family. @@ -3338,8 +3496,41 @@ const ( ) ``` + +## type [NodeCondition]() + +NodeCondition defines model for NodeCondition. + +```go +type NodeCondition struct { + LastTransitionTime time.Time `json:"last_transition_time"` + Reason *string `json:"reason,omitempty"` + Status bool `json:"status"` + Type NodeConditionType `json:"type"` +} +``` + + +## type [NodeConditionType]() + +NodeConditionType defines model for NodeCondition.Type. + +```go +type NodeConditionType string +``` + +Defines values for NodeConditionType. + +```go +const ( + DiskPressure NodeConditionType = "DiskPressure" + HighLoad NodeConditionType = "HighLoad" + MemoryPressure NodeConditionType = "MemoryPressure" +) +``` + -## type [NodeStatusCollectionResponse]() +## type [NodeStatusCollectionResponse]() NodeStatusCollectionResponse defines model for NodeStatusCollectionResponse. @@ -3352,7 +3543,7 @@ type NodeStatusCollectionResponse struct { ``` -## type [NodeStatusResponse]() +## type [NodeStatusResponse]() NodeStatusResponse defines model for NodeStatusResponse. @@ -3382,7 +3573,7 @@ type NodeStatusResponse struct { ``` -## type [OSInfoCollectionResponse]() +## type [OSInfoCollectionResponse]() OSInfoCollectionResponse defines model for OSInfoCollectionResponse. @@ -3395,7 +3586,7 @@ type OSInfoCollectionResponse struct { ``` -## type [OSInfoResponse]() +## type [OSInfoResponse]() OSInfoResponse Operating system information. @@ -3410,7 +3601,7 @@ type OSInfoResponse struct { ``` -## type [OSInfoResultItem]() +## type [OSInfoResultItem]() OSInfoResultItem defines model for OSInfoResultItem. @@ -3428,7 +3619,7 @@ type OSInfoResultItem struct { ``` -## type [PingCollectionResponse]() +## type [PingCollectionResponse]() PingCollectionResponse defines model for PingCollectionResponse. @@ -3441,7 +3632,7 @@ type PingCollectionResponse struct { ``` -## type [PingResponse]() +## type [PingResponse]() PingResponse defines model for PingResponse. @@ -3474,7 +3665,7 @@ type PingResponse struct { ``` -## type [PostJobJSONRequestBody]() +## type [PostJobJSONRequestBody]() PostJobJSONRequestBody defines body for PostJob for application/json ContentType. @@ -3483,7 +3674,7 @@ type PostJobJSONRequestBody = CreateJobRequest ``` -## type [PostJobResponse]() +## type [PostJobResponse]() @@ -3500,7 +3691,7 @@ type PostJobResponse struct { ``` -### func [ParsePostJobResponse]() +### func [ParsePostJobResponse]() ```go func ParsePostJobResponse(rsp *http.Response) (*PostJobResponse, error) @@ -3509,7 +3700,7 @@ func ParsePostJobResponse(rsp *http.Response) (*PostJobResponse, error) ParsePostJobResponse parses an HTTP response from a PostJobWithResponse call -### func \(PostJobResponse\) [Status]() +### func \(PostJobResponse\) [Status]() ```go func (r PostJobResponse) Status() string @@ -3518,7 +3709,7 @@ func (r PostJobResponse) Status() string Status returns HTTPResponse.Status -### func \(PostJobResponse\) [StatusCode]() +### func \(PostJobResponse\) [StatusCode]() ```go func (r PostJobResponse) StatusCode() int @@ -3527,7 +3718,7 @@ func (r PostJobResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [PostNodeCommandExecJSONRequestBody]() +## type [PostNodeCommandExecJSONRequestBody]() PostNodeCommandExecJSONRequestBody defines body for PostNodeCommandExec for application/json ContentType. @@ -3536,7 +3727,7 @@ type PostNodeCommandExecJSONRequestBody = CommandExecRequest ``` -## type [PostNodeCommandExecResponse]() +## type [PostNodeCommandExecResponse]() @@ -3553,7 +3744,7 @@ type PostNodeCommandExecResponse struct { ``` -### func [ParsePostNodeCommandExecResponse]() +### func [ParsePostNodeCommandExecResponse]() ```go func ParsePostNodeCommandExecResponse(rsp *http.Response) (*PostNodeCommandExecResponse, error) @@ -3562,7 +3753,7 @@ func ParsePostNodeCommandExecResponse(rsp *http.Response) (*PostNodeCommandExecR ParsePostNodeCommandExecResponse parses an HTTP response from a PostNodeCommandExecWithResponse call -### func \(PostNodeCommandExecResponse\) [Status]() +### func \(PostNodeCommandExecResponse\) [Status]() ```go func (r PostNodeCommandExecResponse) Status() string @@ -3571,7 +3762,7 @@ func (r PostNodeCommandExecResponse) Status() string Status returns HTTPResponse.Status -### func \(PostNodeCommandExecResponse\) [StatusCode]() +### func \(PostNodeCommandExecResponse\) [StatusCode]() ```go func (r PostNodeCommandExecResponse) StatusCode() int @@ -3580,7 +3771,7 @@ func (r PostNodeCommandExecResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [PostNodeCommandShellJSONRequestBody]() +## type [PostNodeCommandShellJSONRequestBody]() PostNodeCommandShellJSONRequestBody defines body for PostNodeCommandShell for application/json ContentType. @@ -3589,7 +3780,7 @@ type PostNodeCommandShellJSONRequestBody = CommandShellRequest ``` -## type [PostNodeCommandShellResponse]() +## type [PostNodeCommandShellResponse]() @@ -3606,7 +3797,7 @@ type PostNodeCommandShellResponse struct { ``` -### func [ParsePostNodeCommandShellResponse]() +### func [ParsePostNodeCommandShellResponse]() ```go func ParsePostNodeCommandShellResponse(rsp *http.Response) (*PostNodeCommandShellResponse, error) @@ -3615,7 +3806,7 @@ func ParsePostNodeCommandShellResponse(rsp *http.Response) (*PostNodeCommandShel ParsePostNodeCommandShellResponse parses an HTTP response from a PostNodeCommandShellWithResponse call -### func \(PostNodeCommandShellResponse\) [Status]() +### func \(PostNodeCommandShellResponse\) [Status]() ```go func (r PostNodeCommandShellResponse) Status() string @@ -3624,7 +3815,7 @@ func (r PostNodeCommandShellResponse) Status() string Status returns HTTPResponse.Status -### func \(PostNodeCommandShellResponse\) [StatusCode]() +### func \(PostNodeCommandShellResponse\) [StatusCode]() ```go func (r PostNodeCommandShellResponse) StatusCode() int @@ -3633,7 +3824,7 @@ func (r PostNodeCommandShellResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [PostNodeNetworkPingJSONBody]() +## type [PostNodeNetworkPingJSONBody]() PostNodeNetworkPingJSONBody defines parameters for PostNodeNetworkPing. @@ -3645,7 +3836,7 @@ type PostNodeNetworkPingJSONBody struct { ``` -## type [PostNodeNetworkPingJSONRequestBody]() +## type [PostNodeNetworkPingJSONRequestBody]() PostNodeNetworkPingJSONRequestBody defines body for PostNodeNetworkPing for application/json ContentType. @@ -3654,7 +3845,7 @@ type PostNodeNetworkPingJSONRequestBody PostNodeNetworkPingJSONBody ``` -## type [PostNodeNetworkPingResponse]() +## type [PostNodeNetworkPingResponse]() @@ -3671,7 +3862,7 @@ type PostNodeNetworkPingResponse struct { ``` -### func [ParsePostNodeNetworkPingResponse]() +### func [ParsePostNodeNetworkPingResponse]() ```go func ParsePostNodeNetworkPingResponse(rsp *http.Response) (*PostNodeNetworkPingResponse, error) @@ -3680,7 +3871,7 @@ func ParsePostNodeNetworkPingResponse(rsp *http.Response) (*PostNodeNetworkPingR ParsePostNodeNetworkPingResponse parses an HTTP response from a PostNodeNetworkPingWithResponse call -### func \(PostNodeNetworkPingResponse\) [Status]() +### func \(PostNodeNetworkPingResponse\) [Status]() ```go func (r PostNodeNetworkPingResponse) Status() string @@ -3689,7 +3880,7 @@ func (r PostNodeNetworkPingResponse) Status() string Status returns HTTPResponse.Status -### func \(PostNodeNetworkPingResponse\) [StatusCode]() +### func \(PostNodeNetworkPingResponse\) [StatusCode]() ```go func (r PostNodeNetworkPingResponse) StatusCode() int @@ -3698,7 +3889,7 @@ func (r PostNodeNetworkPingResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [PutNodeNetworkDNSJSONRequestBody]() +## type [PutNodeNetworkDNSJSONRequestBody]() PutNodeNetworkDNSJSONRequestBody defines body for PutNodeNetworkDNS for application/json ContentType. @@ -3707,7 +3898,7 @@ type PutNodeNetworkDNSJSONRequestBody = DNSConfigUpdateRequest ``` -## type [PutNodeNetworkDNSResponse]() +## type [PutNodeNetworkDNSResponse]() @@ -3724,7 +3915,7 @@ type PutNodeNetworkDNSResponse struct { ``` -### func [ParsePutNodeNetworkDNSResponse]() +### func [ParsePutNodeNetworkDNSResponse]() ```go func ParsePutNodeNetworkDNSResponse(rsp *http.Response) (*PutNodeNetworkDNSResponse, error) @@ -3733,7 +3924,7 @@ func ParsePutNodeNetworkDNSResponse(rsp *http.Response) (*PutNodeNetworkDNSRespo ParsePutNodeNetworkDNSResponse parses an HTTP response from a PutNodeNetworkDNSWithResponse call -### func \(PutNodeNetworkDNSResponse\) [Status]() +### func \(PutNodeNetworkDNSResponse\) [Status]() ```go func (r PutNodeNetworkDNSResponse) Status() string @@ -3742,7 +3933,7 @@ func (r PutNodeNetworkDNSResponse) Status() string Status returns HTTPResponse.Status -### func \(PutNodeNetworkDNSResponse\) [StatusCode]() +### func \(PutNodeNetworkDNSResponse\) [StatusCode]() ```go func (r PutNodeNetworkDNSResponse) StatusCode() int @@ -3751,7 +3942,7 @@ func (r PutNodeNetworkDNSResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [QueueStatsResponse]() +## type [QueueStatsResponse]() QueueStatsResponse defines model for QueueStatsResponse. @@ -3772,7 +3963,7 @@ type QueueStatsResponse struct { ``` -## type [ReadyResponse]() +## type [ReadyResponse]() ReadyResponse defines model for ReadyResponse. @@ -3787,7 +3978,7 @@ type ReadyResponse struct { ``` -## type [RequestEditorFn]() +## type [RequestEditorFn]() RequestEditorFn is the function signature for the RequestEditor callback function @@ -3796,7 +3987,7 @@ type RequestEditorFn func(ctx context.Context, req *http.Request) error ``` -## type [RetryJobByIDJSONRequestBody]() +## type [RetryJobByIDJSONRequestBody]() RetryJobByIDJSONRequestBody defines body for RetryJobByID for application/json ContentType. @@ -3805,7 +3996,7 @@ type RetryJobByIDJSONRequestBody = RetryJobRequest ``` -## type [RetryJobByIDResponse]() +## type [RetryJobByIDResponse]() @@ -3823,7 +4014,7 @@ type RetryJobByIDResponse struct { ``` -### func [ParseRetryJobByIDResponse]() +### func [ParseRetryJobByIDResponse]() ```go func ParseRetryJobByIDResponse(rsp *http.Response) (*RetryJobByIDResponse, error) @@ -3832,7 +4023,7 @@ func ParseRetryJobByIDResponse(rsp *http.Response) (*RetryJobByIDResponse, error ParseRetryJobByIDResponse parses an HTTP response from a RetryJobByIDWithResponse call -### func \(RetryJobByIDResponse\) [Status]() +### func \(RetryJobByIDResponse\) [Status]() ```go func (r RetryJobByIDResponse) Status() string @@ -3841,7 +4032,7 @@ func (r RetryJobByIDResponse) Status() string Status returns HTTPResponse.Status -### func \(RetryJobByIDResponse\) [StatusCode]() +### func \(RetryJobByIDResponse\) [StatusCode]() ```go func (r RetryJobByIDResponse) StatusCode() int @@ -3850,7 +4041,7 @@ func (r RetryJobByIDResponse) StatusCode() int StatusCode returns HTTPResponse.StatusCode -## type [RetryJobRequest]() +## type [RetryJobRequest]() RetryJobRequest defines model for RetryJobRequest. @@ -3862,7 +4053,7 @@ type RetryJobRequest struct { ``` -## type [StatusResponse]() +## type [StatusResponse]() StatusResponse defines model for StatusResponse. @@ -3894,7 +4085,7 @@ type StatusResponse struct { ``` -## type [StreamInfo]() +## type [StreamInfo]() StreamInfo defines model for StreamInfo. @@ -3914,8 +4105,69 @@ type StreamInfo struct { } ``` + +## type [TimelineEvent]() + +TimelineEvent defines model for TimelineEvent. + +```go +type TimelineEvent struct { + Error *string `json:"error,omitempty"` + Event string `json:"event"` + Hostname *string `json:"hostname,omitempty"` + Message *string `json:"message,omitempty"` + Timestamp time.Time `json:"timestamp"` +} +``` + + +## type [UndrainAgentResponse]() + + + +```go +type UndrainAgentResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Message string `json:"message"` + } + JSON401 *ErrorResponse + JSON403 *ErrorResponse + JSON404 *ErrorResponse + JSON409 *ErrorResponse +} +``` + + +### func [ParseUndrainAgentResponse]() + +```go +func ParseUndrainAgentResponse(rsp *http.Response) (*UndrainAgentResponse, error) +``` + +ParseUndrainAgentResponse parses an HTTP response from a UndrainAgentWithResponse call + + +### func \(UndrainAgentResponse\) [Status]() + +```go +func (r UndrainAgentResponse) Status() string +``` + +Status returns HTTPResponse.Status + + +### func \(UndrainAgentResponse\) [StatusCode]() + +```go +func (r UndrainAgentResponse) StatusCode() int +``` + +StatusCode returns HTTPResponse.StatusCode + -## type [UptimeCollectionResponse]() +## type [UptimeCollectionResponse]() UptimeCollectionResponse defines model for UptimeCollectionResponse. @@ -3928,7 +4180,7 @@ type UptimeCollectionResponse struct { ``` -## type [UptimeResponse]() +## type [UptimeResponse]() UptimeResponse System uptime information. diff --git a/docs/gen/osapi.md b/docs/gen/osapi.md index 7597992..3b4dd2c 100644 --- a/docs/gen/osapi.md +++ b/docs/gen/osapi.md @@ -31,8 +31,10 @@ resp, err := client.Node.Exec(ctx, osapi.ExecRequest{ - [type AgentJobResponse](<#AgentJobResponse>) - [type AgentList](<#AgentList>) - [type AgentService](<#AgentService>) + - [func \(s \*AgentService\) Drain\(ctx context.Context, hostname string\) \(\*Response\[MessageResponse\], error\)](<#AgentService.Drain>) - [func \(s \*AgentService\) Get\(ctx context.Context, hostname string\) \(\*Response\[Agent\], error\)](<#AgentService.Get>) - [func \(s \*AgentService\) List\(ctx context.Context\) \(\*Response\[AgentList\], error\)](<#AgentService.List>) + - [func \(s \*AgentService\) Undrain\(ctx context.Context, hostname string\) \(\*Response\[MessageResponse\], error\)](<#AgentService.Undrain>) - [type AgentState](<#AgentState>) - [type AgentStats](<#AgentStats>) - [type AgentSummary](<#AgentSummary>) @@ -49,6 +51,9 @@ resp, err := client.Node.Exec(ctx, osapi.ExecRequest{ - [type Collection](<#Collection>) - [type CommandResult](<#CommandResult>) - [type ComponentHealth](<#ComponentHealth>) +- [type Condition](<#Condition>) +- [type ConflictError](<#ConflictError>) + - [func \(e \*ConflictError\) Unwrap\(\) error](<#ConflictError.Unwrap>) - [type ConsumerDetail](<#ConsumerDetail>) - [type ConsumerStats](<#ConsumerStats>) - [type DNSConfig](<#DNSConfig>) @@ -79,6 +84,7 @@ resp, err := client.Node.Exec(ctx, osapi.ExecRequest{ - [type LoadResult](<#LoadResult>) - [type Memory](<#Memory>) - [type MemoryResult](<#MemoryResult>) +- [type MessageResponse](<#MessageResponse>) - [type MetricsService](<#MetricsService>) - [func \(s \*MetricsService\) Get\(ctx context.Context\) \(string, error\)](<#MetricsService.Get>) - [type NATSInfo](<#NATSInfo>) @@ -145,7 +151,7 @@ func (e *APIError) Error() string Error returns a formatted error string. -## type [Agent]() +## type [Agent]() Agent represents a registered OSAPI agent. @@ -153,6 +159,7 @@ Agent represents a registered OSAPI agent. type Agent struct { Hostname string Status string + State string Labels map[string]string Architecture string CPUCount int @@ -164,6 +171,8 @@ type Agent struct { Memory *Memory OSInfo *OSInfo Interfaces []NetworkInterface + Conditions []Condition + Timeline []TimelineEvent Uptime string StartedAt time.Time RegisteredAt time.Time @@ -186,7 +195,7 @@ type AgentJobResponse struct { ``` -## type [AgentList]() +## type [AgentList]() AgentList is a collection of agents. @@ -198,7 +207,7 @@ type AgentList struct { ``` -## type [AgentService]() +## type [AgentService]() AgentService provides agent discovery and details operations. @@ -208,8 +217,17 @@ type AgentService struct { } ``` + +### func \(\*AgentService\) [Drain]() + +```go +func (s *AgentService) Drain(ctx context.Context, hostname string) (*Response[MessageResponse], error) +``` + +Drain initiates draining of an agent, stopping it from accepting new jobs while allowing in\-flight jobs to complete. + -### func \(\*AgentService\) [Get]() +### func \(\*AgentService\) [Get]() ```go func (s *AgentService) Get(ctx context.Context, hostname string) (*Response[Agent], error) @@ -218,7 +236,7 @@ func (s *AgentService) Get(ctx context.Context, hostname string) (*Response[Agen Get retrieves detailed information about a specific agent by hostname. -### func \(\*AgentService\) [List]() +### func \(\*AgentService\) [List]() ```go func (s *AgentService) List(ctx context.Context) (*Response[AgentList], error) @@ -226,6 +244,15 @@ func (s *AgentService) List(ctx context.Context) (*Response[AgentList], error) List retrieves all active agents. + +### func \(\*AgentService\) [Undrain]() + +```go +func (s *AgentService) Undrain(ctx context.Context, hostname string) (*Response[MessageResponse], error) +``` + +Undrain resumes job acceptance on a drained agent. + ## type [AgentState]() @@ -434,6 +461,40 @@ type ComponentHealth struct { } ``` + +## type [Condition]() + +Condition represents a node condition evaluated agent\-side. + +```go +type Condition struct { + Type string + Status bool + Reason string + LastTransitionTime time.Time +} +``` + + +## type [ConflictError]() + +ConflictError represents conflict errors \(409\). + +```go +type ConflictError struct { + APIError +} +``` + + +### func \(\*ConflictError\) [Unwrap]() + +```go +func (e *ConflictError) Unwrap() error +``` + +Unwrap returns the underlying APIError. + ## type [ConsumerDetail]() @@ -638,7 +699,7 @@ type JobDetail struct { ``` -## type [JobList]() +## type [JobList]() JobList is a paginated list of jobs. @@ -763,7 +824,7 @@ type ListParams struct { ``` -## type [LoadAverage]() +## type [LoadAverage]() LoadAverage represents system load averages. @@ -789,7 +850,7 @@ type LoadResult struct { ``` -## type [Memory]() +## type [Memory]() Memory represents memory usage information. @@ -814,6 +875,17 @@ type MemoryResult struct { } ``` + +## type [MessageResponse]() + +MessageResponse represents a simple message response from the API. + +```go +type MessageResponse struct { + Message string +} +``` + ## type [MetricsService]() @@ -847,7 +919,7 @@ type NATSInfo struct { ``` -## type [NetworkInterface]() +## type [NetworkInterface]() NetworkInterface represents a network interface on an agent. @@ -1018,7 +1090,7 @@ func (e *NotFoundError) Unwrap() error Unwrap returns the underlying APIError. -## type [OSInfo]() +## type [OSInfo]() OSInfo represents operating system information. @@ -1088,7 +1160,7 @@ type PingResult struct { ``` -## type [QueueStats]() +## type [QueueStats]() QueueStats represents job queue statistics. @@ -1222,9 +1294,9 @@ type SystemStatus struct { ``` -## type [TimelineEvent]() +## type [TimelineEvent]() -TimelineEvent represents a job lifecycle event. +TimelineEvent represents a lifecycle event. Used by both job timelines and agent state transition history. ```go type TimelineEvent struct { @@ -1237,7 +1309,7 @@ type TimelineEvent struct { ``` -## type [UnexpectedStatusError]() +## type [UnexpectedStatusError]() UnexpectedStatusError represents unexpected HTTP status codes. @@ -1248,7 +1320,7 @@ type UnexpectedStatusError struct { ``` -### func \(\*UnexpectedStatusError\) [Unwrap]() +### func \(\*UnexpectedStatusError\) [Unwrap]() ```go func (e *UnexpectedStatusError) Unwrap() error diff --git a/pkg/osapi/agent.go b/pkg/osapi/agent.go index ff2329d..bcec134 100644 --- a/pkg/osapi/agent.go +++ b/pkg/osapi/agent.go @@ -27,6 +27,11 @@ import ( "github.com/osapi-io/osapi-sdk/pkg/osapi/gen" ) +// MessageResponse represents a simple message response from the API. +type MessageResponse struct { + Message string +} + // AgentService provides agent discovery and details operations. type AgentService struct { client *gen.ClientWithResponses @@ -78,3 +83,60 @@ func (s *AgentService) Get( return NewResponse(agentFromGen(resp.JSON200), resp.Body), nil } + +// Drain initiates draining of an agent, stopping it from accepting +// new jobs while allowing in-flight jobs to complete. +func (s *AgentService) Drain( + ctx context.Context, + hostname string, +) (*Response[MessageResponse], error) { + resp, err := s.client.DrainAgentWithResponse(ctx, hostname) + if err != nil { + return nil, fmt.Errorf("drain agent %s: %w", hostname, err) + } + + if err := checkError(resp.StatusCode(), resp.JSON401, resp.JSON403, resp.JSON404, resp.JSON409); err != nil { + return nil, err + } + + if resp.JSON200 == nil { + return nil, &UnexpectedStatusError{APIError{ + StatusCode: resp.StatusCode(), + Message: "nil response body", + }} + } + + msg := MessageResponse{ + Message: resp.JSON200.Message, + } + + return NewResponse(msg, resp.Body), nil +} + +// Undrain resumes job acceptance on a drained agent. +func (s *AgentService) Undrain( + ctx context.Context, + hostname string, +) (*Response[MessageResponse], error) { + resp, err := s.client.UndrainAgentWithResponse(ctx, hostname) + if err != nil { + return nil, fmt.Errorf("undrain agent %s: %w", hostname, err) + } + + if err := checkError(resp.StatusCode(), resp.JSON401, resp.JSON403, resp.JSON404, resp.JSON409); err != nil { + return nil, err + } + + if resp.JSON200 == nil { + return nil, &UnexpectedStatusError{APIError{ + StatusCode: resp.StatusCode(), + Message: "nil response body", + }} + } + + msg := MessageResponse{ + Message: resp.JSON200.Message, + } + + return NewResponse(msg, resp.Body), nil +} diff --git a/pkg/osapi/agent_public_test.go b/pkg/osapi/agent_public_test.go index 0ecbef6..a1ca031 100644 --- a/pkg/osapi/agent_public_test.go +++ b/pkg/osapi/agent_public_test.go @@ -282,6 +282,286 @@ func (suite *AgentPublicTestSuite) TestGetError() { } } +func (suite *AgentPublicTestSuite) TestDrain() { + tests := []struct { + name string + hostname string + validateFunc func(*osapi.Response[osapi.MessageResponse], error) + }{ + { + name: "when draining agent returns success", + hostname: "server1", + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.NoError(err) + suite.NotNil(resp) + suite.Equal("drain initiated for agent server1", resp.Data.Message) + }, + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + server := httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"message":"drain initiated for agent server1"}`)) + }), + ) + defer server.Close() + + sut := osapi.New( + server.URL, + "test-token", + osapi.WithLogger(slog.Default()), + ) + + resp, err := sut.Agent.Drain(suite.ctx, tc.hostname) + tc.validateFunc(resp, err) + }) + } +} + +func (suite *AgentPublicTestSuite) TestDrainError() { + tests := []struct { + name string + serverURL string + serverFunc func() *httptest.Server + validateFunc func(*osapi.Response[osapi.MessageResponse], error) + }{ + { + name: "when server returns 409 returns ConflictError", + serverFunc: func() *httptest.Server { + return httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusConflict) + _, _ = w.Write([]byte(`{"error":"agent already draining"}`)) + }), + ) + }, + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.ConflictError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusConflict, target.StatusCode) + suite.Equal("agent already draining", target.Message) + }, + }, + { + name: "when server returns 404 returns NotFoundError", + serverFunc: func() *httptest.Server { + return httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"agent not found"}`)) + }), + ) + }, + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.NotFoundError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusNotFound, target.StatusCode) + }, + }, + { + name: "when client HTTP error returns wrapped error", + serverURL: "http://127.0.0.1:0", + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.Error(err) + suite.Nil(resp) + suite.Contains(err.Error(), "drain agent") + }, + }, + { + name: "when response JSON200 is nil returns UnexpectedStatusError", + serverFunc: func() *httptest.Server { + return httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) + }), + ) + }, + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.UnexpectedStatusError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusOK, target.StatusCode) + suite.Contains(target.Message, "nil response body") + }, + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + url := tc.serverURL + if tc.serverFunc != nil { + server := tc.serverFunc() + defer server.Close() + url = server.URL + } + + sut := osapi.New( + url, + "test-token", + osapi.WithLogger(slog.Default()), + ) + + resp, err := sut.Agent.Drain(suite.ctx, "test-host") + tc.validateFunc(resp, err) + }) + } +} + +func (suite *AgentPublicTestSuite) TestUndrain() { + tests := []struct { + name string + hostname string + validateFunc func(*osapi.Response[osapi.MessageResponse], error) + }{ + { + name: "when undraining agent returns success", + hostname: "server1", + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.NoError(err) + suite.NotNil(resp) + suite.Equal("undrain initiated for agent server1", resp.Data.Message) + }, + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + server := httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"message":"undrain initiated for agent server1"}`)) + }), + ) + defer server.Close() + + sut := osapi.New( + server.URL, + "test-token", + osapi.WithLogger(slog.Default()), + ) + + resp, err := sut.Agent.Undrain(suite.ctx, tc.hostname) + tc.validateFunc(resp, err) + }) + } +} + +func (suite *AgentPublicTestSuite) TestUndrainError() { + tests := []struct { + name string + serverURL string + serverFunc func() *httptest.Server + validateFunc func(*osapi.Response[osapi.MessageResponse], error) + }{ + { + name: "when server returns 409 returns ConflictError", + serverFunc: func() *httptest.Server { + return httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusConflict) + _, _ = w.Write([]byte(`{"error":"agent not in draining state"}`)) + }), + ) + }, + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.ConflictError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusConflict, target.StatusCode) + suite.Equal("agent not in draining state", target.Message) + }, + }, + { + name: "when server returns 404 returns NotFoundError", + serverFunc: func() *httptest.Server { + return httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"agent not found"}`)) + }), + ) + }, + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.NotFoundError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusNotFound, target.StatusCode) + }, + }, + { + name: "when client HTTP error returns wrapped error", + serverURL: "http://127.0.0.1:0", + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.Error(err) + suite.Nil(resp) + suite.Contains(err.Error(), "undrain agent") + }, + }, + { + name: "when response JSON200 is nil returns UnexpectedStatusError", + serverFunc: func() *httptest.Server { + return httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) + }), + ) + }, + validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.UnexpectedStatusError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusOK, target.StatusCode) + suite.Contains(target.Message, "nil response body") + }, + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + url := tc.serverURL + if tc.serverFunc != nil { + server := tc.serverFunc() + defer server.Close() + url = server.URL + } + + sut := osapi.New( + url, + "test-token", + osapi.WithLogger(slog.Default()), + ) + + resp, err := sut.Agent.Undrain(suite.ctx, "test-host") + tc.validateFunc(resp, err) + }) + } +} + func TestAgentPublicTestSuite(t *testing.T) { suite.Run(t, new(AgentPublicTestSuite)) } diff --git a/pkg/osapi/agent_types.go b/pkg/osapi/agent_types.go index bfb14d7..ee942fa 100644 --- a/pkg/osapi/agent_types.go +++ b/pkg/osapi/agent_types.go @@ -30,6 +30,7 @@ import ( type Agent struct { Hostname string Status string + State string Labels map[string]string Architecture string CPUCount int @@ -41,12 +42,22 @@ type Agent struct { Memory *Memory OSInfo *OSInfo Interfaces []NetworkInterface + Conditions []Condition + Timeline []TimelineEvent Uptime string StartedAt time.Time RegisteredAt time.Time Facts map[string]any } +// Condition represents a node condition evaluated agent-side. +type Condition struct { + Type string + Status bool + Reason string + LastTransitionTime time.Time +} + // AgentList is a collection of agents. type AgentList struct { Agents []Agent @@ -168,6 +179,55 @@ func agentFromGen( a.Facts = *g.Facts } + if g.State != nil { + a.State = string(*g.State) + } + + if g.Conditions != nil { + conditions := make([]Condition, 0, len(*g.Conditions)) + for _, c := range *g.Conditions { + cond := Condition{ + Type: string(c.Type), + Status: c.Status, + LastTransitionTime: c.LastTransitionTime, + } + + if c.Reason != nil { + cond.Reason = *c.Reason + } + + conditions = append(conditions, cond) + } + + a.Conditions = conditions + } + + if g.Timeline != nil { + timeline := make([]TimelineEvent, 0, len(*g.Timeline)) + for _, t := range *g.Timeline { + te := TimelineEvent{ + Event: t.Event, + Timestamp: t.Timestamp.Format(time.RFC3339), + } + + if t.Hostname != nil { + te.Hostname = *t.Hostname + } + + if t.Message != nil { + te.Message = *t.Message + } + + if t.Error != nil { + te.Error = *t.Error + } + + timeline = append(timeline, te) + } + + a.Timeline = timeline + } + return a } diff --git a/pkg/osapi/agent_types_test.go b/pkg/osapi/agent_types_test.go index 7414b31..df424f9 100644 --- a/pkg/osapi/agent_types_test.go +++ b/pkg/osapi/agent_types_test.go @@ -58,6 +58,12 @@ func (suite *AgentTypesTestSuite) TestAgentFromGen() { ipv6 := "fe80::1" mac := "00:11:22:33:44:55" facts := map[string]interface{}{"custom_key": "custom_value"} + state := gen.AgentInfoStateReady + reason := "load avg 0.50 < 4.00" + condTime := now.Add(-30 * time.Minute) + hostname := "web-01" + message := "agent started" + errMsg := "connection lost" return &gen.AgentInfo{ Hostname: "web-01", @@ -96,11 +102,35 @@ func (suite *AgentTypesTestSuite) TestAgentFromGen() { StartedAt: &startedAt, RegisteredAt: &now, Facts: &facts, + State: &state, + Conditions: &[]gen.NodeCondition{ + { + Type: gen.HighLoad, + Status: false, + Reason: &reason, + LastTransitionTime: condTime, + }, + }, + Timeline: &[]gen.TimelineEvent{ + { + Timestamp: startedAt, + Event: "AgentStarted", + Hostname: &hostname, + Message: &message, + }, + { + Timestamp: now, + Event: "AgentFailed", + Hostname: &hostname, + Error: &errMsg, + }, + }, } }(), validateFunc: func(a Agent) { suite.Equal("web-01", a.Hostname) suite.Equal("Ready", a.Status) + suite.Equal("Ready", a.State) suite.Equal(map[string]string{"group": "web", "env": "prod"}, a.Labels) suite.Equal("amd64", a.Architecture) suite.Equal(8, a.CPUCount) @@ -134,6 +164,28 @@ func (suite *AgentTypesTestSuite) TestAgentFromGen() { suite.Equal(startedAt, a.StartedAt) suite.Equal(now, a.RegisteredAt) suite.Equal(map[string]any{"custom_key": "custom_value"}, a.Facts) + + suite.Require().Len(a.Conditions, 1) + suite.Equal("HighLoad", a.Conditions[0].Type) + suite.False(a.Conditions[0].Status) + suite.Equal("load avg 0.50 < 4.00", a.Conditions[0].Reason) + suite.Equal( + now.Add(-30*time.Minute), + a.Conditions[0].LastTransitionTime, + ) + + suite.Require().Len(a.Timeline, 2) + suite.Equal("AgentStarted", a.Timeline[0].Event) + suite.Equal(startedAt.Format(time.RFC3339), a.Timeline[0].Timestamp) + suite.Equal("web-01", a.Timeline[0].Hostname) + suite.Equal("agent started", a.Timeline[0].Message) + suite.Empty(a.Timeline[0].Error) + + suite.Equal("AgentFailed", a.Timeline[1].Event) + suite.Equal(now.Format(time.RFC3339), a.Timeline[1].Timestamp) + suite.Equal("web-01", a.Timeline[1].Hostname) + suite.Empty(a.Timeline[1].Message) + suite.Equal("connection lost", a.Timeline[1].Error) }, }, { @@ -145,6 +197,7 @@ func (suite *AgentTypesTestSuite) TestAgentFromGen() { validateFunc: func(a Agent) { suite.Equal("minimal-host", a.Hostname) suite.Equal("Ready", a.Status) + suite.Empty(a.State) suite.Nil(a.Labels) suite.Empty(a.Architecture) suite.Zero(a.CPUCount) @@ -156,6 +209,8 @@ func (suite *AgentTypesTestSuite) TestAgentFromGen() { suite.Nil(a.Memory) suite.Nil(a.OSInfo) suite.Nil(a.Interfaces) + suite.Nil(a.Conditions) + suite.Nil(a.Timeline) suite.Empty(a.Uptime) suite.True(a.StartedAt.IsZero()) suite.True(a.RegisteredAt.IsZero()) diff --git a/pkg/osapi/errors.go b/pkg/osapi/errors.go index 51854bc..508e742 100644 --- a/pkg/osapi/errors.go +++ b/pkg/osapi/errors.go @@ -77,6 +77,16 @@ func (e *ServerError) Unwrap() error { return &e.APIError } +// ConflictError represents conflict errors (409). +type ConflictError struct { + APIError +} + +// Unwrap returns the underlying APIError. +func (e *ConflictError) Unwrap() error { + return &e.APIError +} + // UnexpectedStatusError represents unexpected HTTP status codes. type UnexpectedStatusError struct { APIError diff --git a/pkg/osapi/errors_public_test.go b/pkg/osapi/errors_public_test.go index c4e1c34..776a69b 100644 --- a/pkg/osapi/errors_public_test.go +++ b/pkg/osapi/errors_public_test.go @@ -113,6 +113,21 @@ func (suite *ErrorsPublicTestSuite) TestErrorFormat() { ) }, }, + { + name: "when ConflictError formats correctly", + err: &osapi.ConflictError{ + APIError: osapi.APIError{ + StatusCode: 409, + Message: "already draining", + }, + }, + validateFunc: func(err error) { + suite.Equal( + "api error (status 409): already draining", + err.Error(), + ) + }, + }, { name: "when UnexpectedStatusError formats correctly", err: &osapi.UnexpectedStatusError{ @@ -203,6 +218,21 @@ func (suite *ErrorsPublicTestSuite) TestErrorsAsUnwrap() { suite.Equal("server failure", target.Message) }, }, + { + name: "when ConflictError is unwrapped via errors.As", + err: fmt.Errorf("wrapped: %w", &osapi.ConflictError{ + APIError: osapi.APIError{ + StatusCode: 409, + Message: "already draining", + }, + }), + validateFunc: func(err error) { + var target *osapi.ConflictError + suite.True(errors.As(err, &target)) + suite.Equal(409, target.StatusCode) + suite.Equal("already draining", target.Message) + }, + }, { name: "when UnexpectedStatusError is unwrapped via errors.As", err: fmt.Errorf("wrapped: %w", &osapi.UnexpectedStatusError{ @@ -293,6 +323,21 @@ func (suite *ErrorsPublicTestSuite) TestErrorsAsAPIError() { suite.Equal("internal error", target.Message) }, }, + { + name: "when ConflictError is matchable as APIError", + err: fmt.Errorf("wrapped: %w", &osapi.ConflictError{ + APIError: osapi.APIError{ + StatusCode: 409, + Message: "conflict", + }, + }), + validateFunc: func(err error) { + var target *osapi.APIError + suite.True(errors.As(err, &target)) + suite.Equal(409, target.StatusCode) + suite.Equal("conflict", target.Message) + }, + }, { name: "when UnexpectedStatusError is matchable as APIError", err: fmt.Errorf("wrapped: %w", &osapi.UnexpectedStatusError{ diff --git a/pkg/osapi/gen/api.yaml b/pkg/osapi/gen/api.yaml index 0dbe61d..104c36d 100644 --- a/pkg/osapi/gen/api.yaml +++ b/pkg/osapi/gen/api.yaml @@ -118,6 +118,116 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' + /agent/{hostname}/drain: + servers: [] + post: + operationId: drainAgent + summary: Drain an agent + description: > + Stop the agent from accepting new jobs. In-flight jobs continue to + completion. + tags: + - Agent_Management_API_agent_operations + security: + - BearerAuth: + - agent:write + parameters: + - name: hostname + in: path + required: true + schema: + type: string + description: The hostname of the agent to drain. + responses: + '200': + description: Agent drain initiated. + content: + application/json: + schema: + type: object + properties: + message: + type: string + required: + - message + '401': + description: Unauthorized - API key required + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - Insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: Agent not found. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '409': + description: Agent already in requested state. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /agent/{hostname}/undrain: + servers: [] + post: + operationId: undrainAgent + summary: Undrain an agent + description: Resume accepting jobs on a drained agent. + tags: + - Agent_Management_API_agent_operations + security: + - BearerAuth: + - agent:write + parameters: + - name: hostname + in: path + required: true + schema: + type: string + description: The hostname of the agent to undrain. + responses: + '200': + description: Agent undrain initiated. + content: + application/json: + schema: + type: object + properties: + message: + type: string + required: + - message + '401': + description: Unauthorized - API key required + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: Forbidden - Insufficient permissions + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: Agent not found. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '409': + description: Agent not in draining or cordoned state. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' /audit: servers: [] get: @@ -1380,6 +1490,23 @@ components: type: object additionalProperties: true description: Extended facts from additional providers. + state: + type: string + enum: + - Ready + - Draining + - Cordoned + description: Agent scheduling state. + conditions: + type: array + items: + $ref: '#/components/schemas/NodeCondition' + description: Evaluated node conditions. + timeline: + type: array + items: + $ref: '#/components/schemas/TimelineEvent' + description: Agent state transition history. required: - hostname - status @@ -1463,6 +1590,43 @@ components: - dual required: - name + NodeCondition: + type: object + properties: + type: + type: string + enum: + - MemoryPressure + - HighLoad + - DiskPressure + status: + type: boolean + reason: + type: string + last_transition_time: + type: string + format: date-time + required: + - type + - status + - last_transition_time + TimelineEvent: + type: object + properties: + timestamp: + type: string + format: date-time + event: + type: string + hostname: + type: string + message: + type: string + error: + type: string + required: + - timestamp + - event AuditEntry: type: object properties: diff --git a/pkg/osapi/gen/client.gen.go b/pkg/osapi/gen/client.gen.go index 5780c87..72dc1a5 100644 --- a/pkg/osapi/gen/client.gen.go +++ b/pkg/osapi/gen/client.gen.go @@ -22,10 +22,17 @@ const ( BearerAuthScopes = "BearerAuth.Scopes" ) +// Defines values for AgentInfoState. +const ( + AgentInfoStateCordoned AgentInfoState = "Cordoned" + AgentInfoStateDraining AgentInfoState = "Draining" + AgentInfoStateReady AgentInfoState = "Ready" +) + // Defines values for AgentInfoStatus. const ( - NotReady AgentInfoStatus = "NotReady" - Ready AgentInfoStatus = "Ready" + AgentInfoStatusNotReady AgentInfoStatus = "NotReady" + AgentInfoStatusReady AgentInfoStatus = "Ready" ) // Defines values for DNSUpdateResultItemStatus. @@ -41,6 +48,13 @@ const ( Inet6 NetworkInterfaceResponseFamily = "inet6" ) +// Defines values for NodeConditionType. +const ( + DiskPressure NodeConditionType = "DiskPressure" + HighLoad NodeConditionType = "HighLoad" + MemoryPressure NodeConditionType = "MemoryPressure" +) + // Defines values for GetJobParamsStatus. const ( GetJobParamsStatusCompleted GetJobParamsStatus = "completed" @@ -67,6 +81,9 @@ type AgentInfo struct { // Architecture CPU architecture. Architecture *string `json:"architecture,omitempty"` + // Conditions Evaluated node conditions. + Conditions *[]NodeCondition `json:"conditions,omitempty"` + // CpuCount Number of logical CPUs. CpuCount *int `json:"cpu_count,omitempty"` @@ -107,13 +124,22 @@ type AgentInfo struct { // StartedAt When the agent process started. StartedAt *time.Time `json:"started_at,omitempty"` + // State Agent scheduling state. + State *AgentInfoState `json:"state,omitempty"` + // Status The current status of the agent. Status AgentInfoStatus `json:"status"` + // Timeline Agent state transition history. + Timeline *[]TimelineEvent `json:"timeline,omitempty"` + // Uptime The system uptime. Uptime *string `json:"uptime,omitempty"` } +// AgentInfoState Agent scheduling state. +type AgentInfoState string + // AgentInfoStatus The current status of the agent. type AgentInfoStatus string @@ -612,6 +638,17 @@ type NetworkInterfaceResponse struct { // NetworkInterfaceResponseFamily IP address family. type NetworkInterfaceResponseFamily string +// NodeCondition defines model for NodeCondition. +type NodeCondition struct { + LastTransitionTime time.Time `json:"last_transition_time"` + Reason *string `json:"reason,omitempty"` + Status bool `json:"status"` + Type NodeConditionType `json:"type"` +} + +// NodeConditionType defines model for NodeCondition.Type. +type NodeConditionType string + // NodeStatusCollectionResponse defines model for NodeStatusCollectionResponse. type NodeStatusCollectionResponse struct { // JobId The job ID used to process this request. @@ -776,6 +813,15 @@ type StreamInfo struct { Name string `json:"name"` } +// TimelineEvent defines model for TimelineEvent. +type TimelineEvent struct { + Error *string `json:"error,omitempty"` + Event string `json:"event"` + Hostname *string `json:"hostname,omitempty"` + Message *string `json:"message,omitempty"` + Timestamp time.Time `json:"timestamp"` +} + // UptimeCollectionResponse defines model for UptimeCollectionResponse. type UptimeCollectionResponse struct { // JobId The job ID used to process this request. @@ -925,6 +971,12 @@ type ClientInterface interface { // GetAgentDetails request GetAgentDetails(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) + // DrainAgent request + DrainAgent(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // UndrainAgent request + UndrainAgent(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetAuditLogs request GetAuditLogs(ctx context.Context, params *GetAuditLogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1037,6 +1089,30 @@ func (c *Client) GetAgentDetails(ctx context.Context, hostname string, reqEditor return c.Client.Do(req) } +func (c *Client) DrainAgent(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDrainAgentRequest(c.Server, hostname) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UndrainAgent(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUndrainAgentRequest(c.Server, hostname) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) GetAuditLogs(ctx context.Context, params *GetAuditLogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetAuditLogsRequest(c.Server, params) if err != nil { @@ -1470,6 +1546,74 @@ func NewGetAgentDetailsRequest(server string, hostname string) (*http.Request, e return req, nil } +// NewDrainAgentRequest generates requests for DrainAgent +func NewDrainAgentRequest(server string, hostname string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "hostname", runtime.ParamLocationPath, hostname) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/agent/%s/drain", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewUndrainAgentRequest generates requests for UndrainAgent +func NewUndrainAgentRequest(server string, hostname string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "hostname", runtime.ParamLocationPath, hostname) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/agent/%s/undrain", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewGetAuditLogsRequest generates requests for GetAuditLogs func NewGetAuditLogsRequest(server string, params *GetAuditLogsParams) (*http.Request, error) { var err error @@ -2483,6 +2627,12 @@ type ClientWithResponsesInterface interface { // GetAgentDetailsWithResponse request GetAgentDetailsWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*GetAgentDetailsResponse, error) + // DrainAgentWithResponse request + DrainAgentWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*DrainAgentResponse, error) + + // UndrainAgentWithResponse request + UndrainAgentWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*UndrainAgentResponse, error) + // GetAuditLogsWithResponse request GetAuditLogsWithResponse(ctx context.Context, params *GetAuditLogsParams, reqEditors ...RequestEditorFn) (*GetAuditLogsResponse, error) @@ -2622,6 +2772,62 @@ func (r GetAgentDetailsResponse) StatusCode() int { return 0 } +type DrainAgentResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Message string `json:"message"` + } + JSON401 *ErrorResponse + JSON403 *ErrorResponse + JSON404 *ErrorResponse + JSON409 *ErrorResponse +} + +// Status returns HTTPResponse.Status +func (r DrainAgentResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r DrainAgentResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type UndrainAgentResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Message string `json:"message"` + } + JSON401 *ErrorResponse + JSON403 *ErrorResponse + JSON404 *ErrorResponse + JSON409 *ErrorResponse +} + +// Status returns HTTPResponse.Status +func (r UndrainAgentResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UndrainAgentResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type GetAuditLogsResponse struct { Body []byte HTTPResponse *http.Response @@ -3278,6 +3484,24 @@ func (c *ClientWithResponses) GetAgentDetailsWithResponse(ctx context.Context, h return ParseGetAgentDetailsResponse(rsp) } +// DrainAgentWithResponse request returning *DrainAgentResponse +func (c *ClientWithResponses) DrainAgentWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*DrainAgentResponse, error) { + rsp, err := c.DrainAgent(ctx, hostname, reqEditors...) + if err != nil { + return nil, err + } + return ParseDrainAgentResponse(rsp) +} + +// UndrainAgentWithResponse request returning *UndrainAgentResponse +func (c *ClientWithResponses) UndrainAgentWithResponse(ctx context.Context, hostname string, reqEditors ...RequestEditorFn) (*UndrainAgentResponse, error) { + rsp, err := c.UndrainAgent(ctx, hostname, reqEditors...) + if err != nil { + return nil, err + } + return ParseUndrainAgentResponse(rsp) +} + // GetAuditLogsWithResponse request returning *GetAuditLogsResponse func (c *ClientWithResponses) GetAuditLogsWithResponse(ctx context.Context, params *GetAuditLogsParams, reqEditors ...RequestEditorFn) (*GetAuditLogsResponse, error) { rsp, err := c.GetAuditLogs(ctx, params, reqEditors...) @@ -3652,6 +3876,118 @@ func ParseGetAgentDetailsResponse(rsp *http.Response) (*GetAgentDetailsResponse, return response, nil } +// ParseDrainAgentResponse parses an HTTP response from a DrainAgentWithResponse call +func ParseDrainAgentResponse(rsp *http.Response) (*DrainAgentResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &DrainAgentResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + Message string `json:"message"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest ErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest ErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest ErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest ErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &dest + + } + + return response, nil +} + +// ParseUndrainAgentResponse parses an HTTP response from a UndrainAgentWithResponse call +func ParseUndrainAgentResponse(rsp *http.Response) (*UndrainAgentResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UndrainAgentResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + Message string `json:"message"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest ErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest ErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest ErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest ErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &dest + + } + + return response, nil +} + // ParseGetAuditLogsResponse parses an HTTP response from a GetAuditLogsWithResponse call func ParseGetAuditLogsResponse(rsp *http.Response) (*GetAuditLogsResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/pkg/osapi/job_types.go b/pkg/osapi/job_types.go index ccd30fc..e37e494 100644 --- a/pkg/osapi/job_types.go +++ b/pkg/osapi/job_types.go @@ -62,15 +62,6 @@ type AgentJobResponse struct { Data any } -// TimelineEvent represents a job lifecycle event. -type TimelineEvent struct { - Timestamp string - Event string - Hostname string - Message string - Error string -} - // JobList is a paginated list of jobs. type JobList struct { Items []JobDetail diff --git a/pkg/osapi/response.go b/pkg/osapi/response.go index 8ee4e96..59987fc 100644 --- a/pkg/osapi/response.go +++ b/pkg/osapi/response.go @@ -70,6 +70,8 @@ func checkError( return &AuthError{APIError{StatusCode: statusCode, Message: msg}} case 404: return &NotFoundError{APIError{StatusCode: statusCode, Message: msg}} + case 409: + return &ConflictError{APIError{StatusCode: statusCode, Message: msg}} case 500: return &ServerError{APIError{StatusCode: statusCode, Message: msg}} default: diff --git a/pkg/osapi/response_test.go b/pkg/osapi/response_test.go index b5ad950..9cba2fa 100644 --- a/pkg/osapi/response_test.go +++ b/pkg/osapi/response_test.go @@ -151,6 +151,32 @@ func (suite *ResponseTestSuite) TestCheckErrorNotFound() { } } +func (suite *ResponseTestSuite) TestCheckErrorConflict() { + tests := []struct { + name string + statusCode int + validateFunc func(error) + }{ + { + name: "when status is 409", + statusCode: 409, + validateFunc: func(err error) { + var target *ConflictError + suite.True(errors.As(err, &target)) + suite.Equal(409, target.StatusCode) + }, + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + err := checkError(tc.statusCode) + suite.Error(err) + tc.validateFunc(err) + }) + } +} + func (suite *ResponseTestSuite) TestCheckErrorServer() { tests := []struct { name string diff --git a/pkg/osapi/types.go b/pkg/osapi/types.go new file mode 100644 index 0000000..eae7db1 --- /dev/null +++ b/pkg/osapi/types.go @@ -0,0 +1,31 @@ +// Copyright (c) 2026 John Dewey + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +package osapi + +// TimelineEvent represents a lifecycle event. Used by both job +// timelines and agent state transition history. +type TimelineEvent struct { + Timestamp string + Event string + Hostname string + Message string + Error string +} From afcd9cc54287fcdfaf6f92ae3864a7780512554a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Thu, 5 Mar 2026 16:17:22 -0800 Subject: [PATCH 2/2] refactor(sdk): consolidate fragmented tests into table-driven suites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge split test methods (TestFoo, TestFooError, TestFooNilResponse) into single table-driven methods per function under test. Reduces ~150 suite methods to ~45 while preserving all 290 test cases. Add explicit one-suite-method-per-function rule to CLAUDE.md and docs/development.md to prevent future fragmentation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- CLAUDE.md | 1 + docs/development.md | 4 + pkg/osapi/agent_public_test.go | 317 ++--- pkg/osapi/audit_public_test.go | 289 ++--- pkg/osapi/health_public_test.go | 115 +- pkg/osapi/job_public_test.go | 816 ++++--------- pkg/osapi/metrics_public_test.go | 135 +-- pkg/osapi/node_public_test.go | 1955 ++++++++++-------------------- pkg/osapi/osapi_public_test.go | 37 +- pkg/osapi/response_test.go | 153 +-- 10 files changed, 1199 insertions(+), 2623 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e587796..046bb2d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -65,6 +65,7 @@ func FunctionName( - Suite naming: `*_public_test.go` → `{Name}PublicTestSuite`, `*_test.go` → `{Name}TestSuite` - Use `testify/suite` with table-driven patterns +- One suite method per function under test — all scenarios (success, errors, edge cases) as rows in one table ### Go Patterns diff --git a/docs/development.md b/docs/development.md index 339e979..cb37209 100644 --- a/docs/development.md +++ b/docs/development.md @@ -65,6 +65,10 @@ go test -run TestName -v ./pkg/osapi/... # Run a single test exported functions. - Use `testify/suite` with table-driven patterns. - Table-driven structure with `validateFunc` callbacks. +- **One suite method per function under test.** All scenarios for a function + (success, error codes, transport failures, nil responses) belong as rows in a + single table — never split into separate `TestFoo`, `TestFooError`, + `TestFooNilResponse` methods. ## Branching diff --git a/pkg/osapi/agent_public_test.go b/pkg/osapi/agent_public_test.go index a1ca031..cdeaccd 100644 --- a/pkg/osapi/agent_public_test.go +++ b/pkg/osapi/agent_public_test.go @@ -46,10 +46,17 @@ func (suite *AgentPublicTestSuite) SetupTest() { func (suite *AgentPublicTestSuite) TestList() { tests := []struct { name string + handler http.HandlerFunc + serverURL string validateFunc func(*osapi.Response[osapi.AgentList], error) }{ { name: "when requesting agents returns no error", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"agents":[],"total":0}`)) + }, validateFunc: func(resp *osapi.Response[osapi.AgentList], err error) { suite.NoError(err) suite.NotNil(resp) @@ -57,48 +64,12 @@ func (suite *AgentPublicTestSuite) TestList() { suite.Empty(resp.Data.Agents) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"agents":[],"total":0}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Agent.List(suite.ctx) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *AgentPublicTestSuite) TestListError() { - tests := []struct { - name string - serverURL string - serverFunc func() *httptest.Server - validateFunc func(*osapi.Response[osapi.AgentList], error) - }{ { name: "when server returns 401 returns AuthError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusUnauthorized) - _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) - }), - ) + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) }, validateFunc: func(resp *osapi.Response[osapi.AgentList], err error) { suite.Error(err) @@ -120,13 +91,9 @@ func (suite *AgentPublicTestSuite) TestListError() { }, { name: "when response JSON200 is nil returns UnexpectedStatusError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - }), - ) + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) }, validateFunc: func(resp *osapi.Response[osapi.AgentList], err error) { suite.Error(err) @@ -143,8 +110,8 @@ func (suite *AgentPublicTestSuite) TestListError() { for _, tc := range tests { suite.Run(tc.name, func() { url := tc.serverURL - if tc.serverFunc != nil { - server := tc.serverFunc() + if tc.handler != nil { + server := httptest.NewServer(tc.handler) defer server.Close() url = server.URL } @@ -164,12 +131,19 @@ func (suite *AgentPublicTestSuite) TestListError() { func (suite *AgentPublicTestSuite) TestGet() { tests := []struct { name string + handler http.HandlerFunc + serverURL string hostname string validateFunc func(*osapi.Response[osapi.Agent], error) }{ { name: "when requesting agent details returns no error", hostname: "server1", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"hostname":"server1","status":"Ready"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Agent], err error) { suite.NoError(err) suite.NotNil(resp) @@ -177,48 +151,13 @@ func (suite *AgentPublicTestSuite) TestGet() { suite.Equal("Ready", resp.Data.Status) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"hostname":"server1","status":"Ready"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Agent.Get(suite.ctx, tc.hostname) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *AgentPublicTestSuite) TestGetError() { - tests := []struct { - name string - serverURL string - serverFunc func() *httptest.Server - validateFunc func(*osapi.Response[osapi.Agent], error) - }{ { - name: "when server returns 404 returns NotFoundError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(`{"error":"agent not found"}`)) - }), - ) + name: "when server returns 404 returns NotFoundError", + hostname: "unknown-host", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"agent not found"}`)) }, validateFunc: func(resp *osapi.Response[osapi.Agent], err error) { suite.Error(err) @@ -232,6 +171,7 @@ func (suite *AgentPublicTestSuite) TestGetError() { }, { name: "when client HTTP error returns wrapped error", + hostname: "unknown-host", serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.Agent], err error) { suite.Error(err) @@ -240,14 +180,11 @@ func (suite *AgentPublicTestSuite) TestGetError() { }, }, { - name: "when response JSON200 is nil returns UnexpectedStatusError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - }), - ) + name: "when response JSON200 is nil returns UnexpectedStatusError", + hostname: "unknown-host", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) }, validateFunc: func(resp *osapi.Response[osapi.Agent], err error) { suite.Error(err) @@ -264,8 +201,8 @@ func (suite *AgentPublicTestSuite) TestGetError() { for _, tc := range tests { suite.Run(tc.name, func() { url := tc.serverURL - if tc.serverFunc != nil { - server := tc.serverFunc() + if tc.handler != nil { + server := httptest.NewServer(tc.handler) defer server.Close() url = server.URL } @@ -276,7 +213,7 @@ func (suite *AgentPublicTestSuite) TestGetError() { osapi.WithLogger(slog.Default()), ) - resp, err := sut.Agent.Get(suite.ctx, "unknown-host") + resp, err := sut.Agent.Get(suite.ctx, tc.hostname) tc.validateFunc(resp, err) }) } @@ -285,60 +222,32 @@ func (suite *AgentPublicTestSuite) TestGetError() { func (suite *AgentPublicTestSuite) TestDrain() { tests := []struct { name string + handler http.HandlerFunc + serverURL string hostname string validateFunc func(*osapi.Response[osapi.MessageResponse], error) }{ { name: "when draining agent returns success", hostname: "server1", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"message":"drain initiated for agent server1"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.NoError(err) suite.NotNil(resp) suite.Equal("drain initiated for agent server1", resp.Data.Message) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"message":"drain initiated for agent server1"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Agent.Drain(suite.ctx, tc.hostname) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *AgentPublicTestSuite) TestDrainError() { - tests := []struct { - name string - serverURL string - serverFunc func() *httptest.Server - validateFunc func(*osapi.Response[osapi.MessageResponse], error) - }{ { - name: "when server returns 409 returns ConflictError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusConflict) - _, _ = w.Write([]byte(`{"error":"agent already draining"}`)) - }), - ) + name: "when server returns 409 returns ConflictError", + hostname: "test-host", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusConflict) + _, _ = w.Write([]byte(`{"error":"agent already draining"}`)) }, validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.Error(err) @@ -351,15 +260,12 @@ func (suite *AgentPublicTestSuite) TestDrainError() { }, }, { - name: "when server returns 404 returns NotFoundError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(`{"error":"agent not found"}`)) - }), - ) + name: "when server returns 404 returns NotFoundError", + hostname: "test-host", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"agent not found"}`)) }, validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.Error(err) @@ -372,6 +278,7 @@ func (suite *AgentPublicTestSuite) TestDrainError() { }, { name: "when client HTTP error returns wrapped error", + hostname: "test-host", serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.Error(err) @@ -380,14 +287,11 @@ func (suite *AgentPublicTestSuite) TestDrainError() { }, }, { - name: "when response JSON200 is nil returns UnexpectedStatusError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - }), - ) + name: "when response JSON200 is nil returns UnexpectedStatusError", + hostname: "test-host", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) }, validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.Error(err) @@ -404,8 +308,8 @@ func (suite *AgentPublicTestSuite) TestDrainError() { for _, tc := range tests { suite.Run(tc.name, func() { url := tc.serverURL - if tc.serverFunc != nil { - server := tc.serverFunc() + if tc.handler != nil { + server := httptest.NewServer(tc.handler) defer server.Close() url = server.URL } @@ -416,7 +320,7 @@ func (suite *AgentPublicTestSuite) TestDrainError() { osapi.WithLogger(slog.Default()), ) - resp, err := sut.Agent.Drain(suite.ctx, "test-host") + resp, err := sut.Agent.Drain(suite.ctx, tc.hostname) tc.validateFunc(resp, err) }) } @@ -425,60 +329,32 @@ func (suite *AgentPublicTestSuite) TestDrainError() { func (suite *AgentPublicTestSuite) TestUndrain() { tests := []struct { name string + handler http.HandlerFunc + serverURL string hostname string validateFunc func(*osapi.Response[osapi.MessageResponse], error) }{ { name: "when undraining agent returns success", hostname: "server1", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"message":"undrain initiated for agent server1"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.NoError(err) suite.NotNil(resp) suite.Equal("undrain initiated for agent server1", resp.Data.Message) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"message":"undrain initiated for agent server1"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Agent.Undrain(suite.ctx, tc.hostname) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *AgentPublicTestSuite) TestUndrainError() { - tests := []struct { - name string - serverURL string - serverFunc func() *httptest.Server - validateFunc func(*osapi.Response[osapi.MessageResponse], error) - }{ { - name: "when server returns 409 returns ConflictError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusConflict) - _, _ = w.Write([]byte(`{"error":"agent not in draining state"}`)) - }), - ) + name: "when server returns 409 returns ConflictError", + hostname: "test-host", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusConflict) + _, _ = w.Write([]byte(`{"error":"agent not in draining state"}`)) }, validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.Error(err) @@ -491,15 +367,12 @@ func (suite *AgentPublicTestSuite) TestUndrainError() { }, }, { - name: "when server returns 404 returns NotFoundError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(`{"error":"agent not found"}`)) - }), - ) + name: "when server returns 404 returns NotFoundError", + hostname: "test-host", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"agent not found"}`)) }, validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.Error(err) @@ -512,6 +385,7 @@ func (suite *AgentPublicTestSuite) TestUndrainError() { }, { name: "when client HTTP error returns wrapped error", + hostname: "test-host", serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.Error(err) @@ -520,14 +394,11 @@ func (suite *AgentPublicTestSuite) TestUndrainError() { }, }, { - name: "when response JSON200 is nil returns UnexpectedStatusError", - serverFunc: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - }), - ) + name: "when response JSON200 is nil returns UnexpectedStatusError", + hostname: "test-host", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) }, validateFunc: func(resp *osapi.Response[osapi.MessageResponse], err error) { suite.Error(err) @@ -544,8 +415,8 @@ func (suite *AgentPublicTestSuite) TestUndrainError() { for _, tc := range tests { suite.Run(tc.name, func() { url := tc.serverURL - if tc.serverFunc != nil { - server := tc.serverFunc() + if tc.handler != nil { + server := httptest.NewServer(tc.handler) defer server.Close() url = server.URL } @@ -556,7 +427,7 @@ func (suite *AgentPublicTestSuite) TestUndrainError() { osapi.WithLogger(slog.Default()), ) - resp, err := sut.Agent.Undrain(suite.ctx, "test-host") + resp, err := sut.Agent.Undrain(suite.ctx, tc.hostname) tc.validateFunc(resp, err) }) } diff --git a/pkg/osapi/audit_public_test.go b/pkg/osapi/audit_public_test.go index 96adadd..7cb8735 100644 --- a/pkg/osapi/audit_public_test.go +++ b/pkg/osapi/audit_public_test.go @@ -46,6 +46,8 @@ func (suite *AuditPublicTestSuite) SetupTest() { func (suite *AuditPublicTestSuite) TestList() { tests := []struct { name string + handler http.HandlerFunc + serverURL string limit int offset int validateFunc func(*osapi.Response[osapi.AuditList], error) @@ -54,6 +56,11 @@ func (suite *AuditPublicTestSuite) TestList() { name: "when listing audit entries returns audit list", limit: 20, offset: 0, + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"items":[],"total_items":0}`)) + }), validateFunc: func(resp *osapi.Response[osapi.AuditList], err error) { suite.NoError(err) suite.NotNil(resp) @@ -61,48 +68,15 @@ func (suite *AuditPublicTestSuite) TestList() { suite.Empty(resp.Data.Items) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"items":[],"total_items":0}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Audit.List(suite.ctx, tc.limit, tc.offset) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *AuditPublicTestSuite) TestListError() { - tests := []struct { - name string - setupServer func() *httptest.Server - validateFunc func(*osapi.Response[osapi.AuditList], error) - }{ { - name: "when server returns 401 returns AuthError", - setupServer: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusUnauthorized) - _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) - }), - ) - }, + name: "when server returns 401 returns AuthError", + limit: 20, + offset: 0, + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) + }), validateFunc: func(resp *osapi.Response[osapi.AuditList], err error) { suite.Error(err) suite.Nil(resp) @@ -113,15 +87,10 @@ func (suite *AuditPublicTestSuite) TestListError() { }, }, { - name: "when HTTP request fails returns error", - setupServer: func() *httptest.Server { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - return server - }, + name: "when client HTTP request fails returns error", + limit: 20, + offset: 0, + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.AuditList], err error) { suite.Error(err) suite.Nil(resp) @@ -129,15 +98,13 @@ func (suite *AuditPublicTestSuite) TestListError() { }, }, { - name: "when response body is nil returns UnexpectedStatusError", - setupServer: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - }), - ) - }, + name: "when response body is nil returns UnexpectedStatusError", + limit: 20, + offset: 0, + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) + }), validateFunc: func(resp *osapi.Response[osapi.AuditList], err error) { suite.Error(err) suite.Nil(resp) @@ -152,16 +119,20 @@ func (suite *AuditPublicTestSuite) TestListError() { for _, tc := range tests { suite.Run(tc.name, func() { - server := tc.setupServer() - defer server.Close() + serverURL := tc.serverURL + if tc.handler != nil { + server := httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Audit.List(suite.ctx, 20, 0) + resp, err := sut.Audit.List(suite.ctx, tc.limit, tc.offset) tc.validateFunc(resp, err) }) } @@ -170,12 +141,23 @@ func (suite *AuditPublicTestSuite) TestListError() { func (suite *AuditPublicTestSuite) TestGet() { tests := []struct { name string + handler http.HandlerFunc + serverURL string id string validateFunc func(*osapi.Response[osapi.AuditEntry], error) }{ { name: "when valid UUID returns audit entry", id: "550e8400-e29b-41d4-a716-446655440000", + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write( + []byte( + `{"entry":{"id":"550e8400-e29b-41d4-a716-446655440000","timestamp":"2026-01-01T00:00:00Z","user":"admin","roles":["admin"],"method":"GET","path":"/api/v1/health","response_code":200,"duration_ms":5,"source_ip":"127.0.0.1"}}`, + ), + ) + }), validateFunc: func(resp *osapi.Response[osapi.AuditEntry], err error) { suite.NoError(err) suite.NotNil(resp) @@ -188,57 +170,28 @@ func (suite *AuditPublicTestSuite) TestGet() { { name: "when invalid UUID returns error", id: "not-a-uuid", + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write( + []byte( + `{"entry":{"id":"550e8400-e29b-41d4-a716-446655440000","timestamp":"2026-01-01T00:00:00Z","user":"admin","roles":["admin"],"method":"GET","path":"/api/v1/health","response_code":200,"duration_ms":5,"source_ip":"127.0.0.1"}}`, + ), + ) + }), validateFunc: func(resp *osapi.Response[osapi.AuditEntry], err error) { suite.Error(err) suite.Nil(resp) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write( - []byte( - `{"entry":{"id":"550e8400-e29b-41d4-a716-446655440000","timestamp":"2026-01-01T00:00:00Z","user":"admin","roles":["admin"],"method":"GET","path":"/api/v1/health","response_code":200,"duration_ms":5,"source_ip":"127.0.0.1"}}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Audit.Get(suite.ctx, tc.id) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *AuditPublicTestSuite) TestGetError() { - tests := []struct { - name string - setupServer func() *httptest.Server - validateFunc func(*osapi.Response[osapi.AuditEntry], error) - }{ { name: "when server returns 404 returns NotFoundError", - setupServer: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(`{"error":"audit entry not found"}`)) - }), - ) - }, + id: "550e8400-e29b-41d4-a716-446655440000", + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"audit entry not found"}`)) + }), validateFunc: func(resp *osapi.Response[osapi.AuditEntry], err error) { suite.Error(err) suite.Nil(resp) @@ -249,15 +202,9 @@ func (suite *AuditPublicTestSuite) TestGetError() { }, }, { - name: "when HTTP request fails returns error", - setupServer: func() *httptest.Server { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - return server - }, + name: "when client HTTP request fails returns error", + id: "550e8400-e29b-41d4-a716-446655440000", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.AuditEntry], err error) { suite.Error(err) suite.Nil(resp) @@ -266,14 +213,11 @@ func (suite *AuditPublicTestSuite) TestGetError() { }, { name: "when response body is nil returns UnexpectedStatusError", - setupServer: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - }), - ) - }, + id: "550e8400-e29b-41d4-a716-446655440000", + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) + }), validateFunc: func(resp *osapi.Response[osapi.AuditEntry], err error) { suite.Error(err) suite.Nil(resp) @@ -288,16 +232,20 @@ func (suite *AuditPublicTestSuite) TestGetError() { for _, tc := range tests { suite.Run(tc.name, func() { - server := tc.setupServer() - defer server.Close() + serverURL := tc.serverURL + if tc.handler != nil { + server := httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Audit.Get(suite.ctx, "550e8400-e29b-41d4-a716-446655440000") + resp, err := sut.Audit.Get(suite.ctx, tc.id) tc.validateFunc(resp, err) }) } @@ -306,10 +254,17 @@ func (suite *AuditPublicTestSuite) TestGetError() { func (suite *AuditPublicTestSuite) TestExport() { tests := []struct { name string + handler http.HandlerFunc + serverURL string validateFunc func(*osapi.Response[osapi.AuditList], error) }{ { name: "when exporting audit entries returns audit list", + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"items":[],"total_items":0}`)) + }), validateFunc: func(resp *osapi.Response[osapi.AuditList], err error) { suite.NoError(err) suite.NotNil(resp) @@ -317,48 +272,13 @@ func (suite *AuditPublicTestSuite) TestExport() { suite.Empty(resp.Data.Items) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"items":[],"total_items":0}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Audit.Export(suite.ctx) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *AuditPublicTestSuite) TestExportError() { - tests := []struct { - name string - setupServer func() *httptest.Server - validateFunc func(*osapi.Response[osapi.AuditList], error) - }{ { name: "when server returns 401 returns AuthError", - setupServer: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusUnauthorized) - _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) - }), - ) - }, + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) + }), validateFunc: func(resp *osapi.Response[osapi.AuditList], err error) { suite.Error(err) suite.Nil(resp) @@ -369,15 +289,8 @@ func (suite *AuditPublicTestSuite) TestExportError() { }, }, { - name: "when HTTP request fails returns error", - setupServer: func() *httptest.Server { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - return server - }, + name: "when client HTTP request fails returns error", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.AuditList], err error) { suite.Error(err) suite.Nil(resp) @@ -386,14 +299,10 @@ func (suite *AuditPublicTestSuite) TestExportError() { }, { name: "when response body is nil returns UnexpectedStatusError", - setupServer: func() *httptest.Server { - return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - }), - ) - }, + handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) + }), validateFunc: func(resp *osapi.Response[osapi.AuditList], err error) { suite.Error(err) suite.Nil(resp) @@ -408,11 +317,15 @@ func (suite *AuditPublicTestSuite) TestExportError() { for _, tc := range tests { suite.Run(tc.name, func() { - server := tc.setupServer() - defer server.Close() + serverURL := tc.serverURL + if tc.handler != nil { + server := httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) diff --git a/pkg/osapi/health_public_test.go b/pkg/osapi/health_public_test.go index aa784d7..6a7e54c 100644 --- a/pkg/osapi/health_public_test.go +++ b/pkg/osapi/health_public_test.go @@ -43,6 +43,19 @@ func (suite *HealthPublicTestSuite) SetupTest() { suite.ctx = context.Background() } +func (suite *HealthPublicTestSuite) runner( + handler http.HandlerFunc, + serverURL string, +) string { + if handler != nil { + server := httptest.NewServer(handler) + suite.T().Cleanup(server.Close) + return server.URL + } + + return serverURL +} + func (suite *HealthPublicTestSuite) TestLiveness() { tests := []struct { name string @@ -92,15 +105,8 @@ func (suite *HealthPublicTestSuite) TestLiveness() { for _, tc := range tests { suite.Run(tc.name, func() { - serverURL := tc.serverURL - if tc.handler != nil { - server := httptest.NewServer(tc.handler) - defer server.Close() - serverURL = server.URL - } - sut := osapi.New( - serverURL, + suite.runner(tc.handler, tc.serverURL), "test-token", osapi.WithLogger(slog.Default()), ) @@ -173,35 +179,6 @@ func (suite *HealthPublicTestSuite) TestReady() { suite.Contains(target.Message, "unexpected status") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - serverURL := tc.serverURL - if tc.handler != nil { - server := httptest.NewServer(tc.handler) - defer server.Close() - serverURL = server.URL - } - - sut := osapi.New( - serverURL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Health.Ready(suite.ctx) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *HealthPublicTestSuite) TestReady503() { - tests := []struct { - name string - handler http.HandlerFunc - validateFunc func(*osapi.Response[osapi.ReadyStatus], error) - }{ { name: "when server returns 503 returns ready status with ServiceUnavailable", handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { @@ -237,11 +214,8 @@ func (suite *HealthPublicTestSuite) TestReady503() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer(tc.handler) - defer server.Close() - sut := osapi.New( - server.URL, + suite.runner(tc.handler, tc.serverURL), "test-token", osapi.WithLogger(slog.Default()), ) @@ -316,35 +290,6 @@ func (suite *HealthPublicTestSuite) TestStatus() { suite.Contains(target.Message, "unexpected status") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - serverURL := tc.serverURL - if tc.handler != nil { - server := httptest.NewServer(tc.handler) - defer server.Close() - serverURL = server.URL - } - - sut := osapi.New( - serverURL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Health.Status(suite.ctx) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *HealthPublicTestSuite) TestStatus503() { - tests := []struct { - name string - handler http.HandlerFunc - validateFunc func(*osapi.Response[osapi.SystemStatus], error) - }{ { name: "when server returns 503 returns status with ServiceUnavailable", handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { @@ -375,31 +320,6 @@ func (suite *HealthPublicTestSuite) TestStatus503() { suite.Contains(target.Message, "nil response body") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer(tc.handler) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Health.Status(suite.ctx) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *HealthPublicTestSuite) TestStatusAuthError() { - tests := []struct { - name string - handler http.HandlerFunc - validateFunc func(*osapi.Response[osapi.SystemStatus], error) - }{ { name: "when server returns 401 returns AuthError", handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { @@ -436,11 +356,8 @@ func (suite *HealthPublicTestSuite) TestStatusAuthError() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer(tc.handler) - defer server.Close() - sut := osapi.New( - server.URL, + suite.runner(tc.handler, tc.serverURL), "test-token", osapi.WithLogger(slog.Default()), ) diff --git a/pkg/osapi/job_public_test.go b/pkg/osapi/job_public_test.go index 0722079..8fb7cea 100644 --- a/pkg/osapi/job_public_test.go +++ b/pkg/osapi/job_public_test.go @@ -46,12 +46,23 @@ func (suite *JobPublicTestSuite) SetupTest() { func (suite *JobPublicTestSuite) TestCreate() { tests := []struct { name string + handler http.HandlerFunc + serverURL string operation map[string]interface{} target string validateFunc func(*osapi.Response[osapi.JobCreated], error) }{ { - name: "when creating job returns response", + name: "when creating job returns response", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + _, _ = w.Write( + []byte( + `{"job_id":"550e8400-e29b-41d4-a716-446655440000","status":"pending"}`, + ), + ) + }, operation: map[string]interface{}{"type": "system.hostname.get"}, target: "_any", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { @@ -61,42 +72,15 @@ func (suite *JobPublicTestSuite) TestCreate() { suite.Equal("pending", resp.Data.Status) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusCreated) - _, _ = w.Write( - []byte( - `{"job_id":"550e8400-e29b-41d4-a716-446655440000","status":"pending"}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Create(suite.ctx, tc.operation, tc.target) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestCreateError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobCreated], error) - }{ { name: "when server returns 400 returns ValidationError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + _, _ = w.Write([]byte(`{"error":"validation failed"}`)) + }, + operation: map[string]interface{}{}, + target: "_any", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { suite.Error(err) suite.Nil(resp) @@ -106,72 +90,24 @@ func (suite *JobPublicTestSuite) TestCreateError() { suite.Equal(http.StatusBadRequest, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusBadRequest) - _, _ = w.Write([]byte(`{"error":"validation failed"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Create(suite.ctx, map[string]interface{}{}, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestCreateHTTPError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobCreated], error) - }{ { - name: "when HTTP request fails returns error", + name: "when HTTP request fails returns error", + serverURL: "http://127.0.0.1:0", + operation: map[string]interface{}{}, + target: "_any", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "create job") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Create(suite.ctx, map[string]interface{}{}, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestCreateNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobCreated], error) - }{ { name: "when server returns 201 with empty body returns UnexpectedStatusError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusCreated) + }, + operation: map[string]interface{}{}, + target: "_any", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { suite.Error(err) suite.Nil(resp) @@ -185,20 +121,26 @@ func (suite *JobPublicTestSuite) TestCreateNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusCreated) - }), + var ( + serverURL string + server *httptest.Server ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + } else { + server = httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Job.Create(suite.ctx, map[string]interface{}{}, "_any") + resp, err := sut.Job.Create(suite.ctx, tc.operation, tc.target) tc.validateFunc(resp, err) }) } @@ -207,12 +149,23 @@ func (suite *JobPublicTestSuite) TestCreateNilResponse() { func (suite *JobPublicTestSuite) TestGet() { tests := []struct { name string + handler http.HandlerFunc + serverURL string id string validateFunc func(*osapi.Response[osapi.JobDetail], error) }{ { name: "when valid UUID returns response", - id: "550e8400-e29b-41d4-a716-446655440000", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write( + []byte( + `{"id":"550e8400-e29b-41d4-a716-446655440000","status":"completed"}`, + ), + ) + }, + id: "550e8400-e29b-41d4-a716-446655440000", validateFunc: func(resp *osapi.Response[osapi.JobDetail], err error) { suite.NoError(err) suite.NotNil(resp) @@ -222,83 +175,38 @@ func (suite *JobPublicTestSuite) TestGet() { }, { name: "when invalid UUID returns error", - id: "not-a-uuid", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write( + []byte( + `{"id":"550e8400-e29b-41d4-a716-446655440000","status":"completed"}`, + ), + ) + }, + id: "not-a-uuid", validateFunc: func(resp *osapi.Response[osapi.JobDetail], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "invalid job ID") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write( - []byte( - `{"id":"550e8400-e29b-41d4-a716-446655440000","status":"completed"}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Get(suite.ctx, tc.id) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestGetHTTPError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobDetail], error) - }{ { - name: "when HTTP request fails returns error", + name: "when HTTP request fails returns error", + serverURL: "http://127.0.0.1:0", + id: "00000000-0000-0000-0000-000000000000", validateFunc: func(resp *osapi.Response[osapi.JobDetail], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "get job") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Get(suite.ctx, "00000000-0000-0000-0000-000000000000") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestGetNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobDetail], error) - }{ { name: "when server returns 200 with empty body returns UnexpectedStatusError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, + id: "00000000-0000-0000-0000-000000000000", validateFunc: func(resp *osapi.Response[osapi.JobDetail], err error) { suite.Error(err) suite.Nil(resp) @@ -308,36 +216,14 @@ func (suite *JobPublicTestSuite) TestGetNilResponse() { suite.Contains(target.Message, "nil response body") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Get(suite.ctx, "00000000-0000-0000-0000-000000000000") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestGetNotFound() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobDetail], error) - }{ { name: "when server returns 404 returns NotFoundError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"job not found"}`)) + }, + id: "550e8400-e29b-41d4-a716-446655440000", validateFunc: func(resp *osapi.Response[osapi.JobDetail], err error) { suite.Error(err) suite.Nil(resp) @@ -352,22 +238,26 @@ func (suite *JobPublicTestSuite) TestGetNotFound() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(`{"error":"job not found"}`)) - }), + var ( + serverURL string + server *httptest.Server ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + } else { + server = httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Job.Get(suite.ctx, "550e8400-e29b-41d4-a716-446655440000") + resp, err := sut.Job.Get(suite.ctx, tc.id) tc.validateFunc(resp, err) }) } @@ -376,87 +266,49 @@ func (suite *JobPublicTestSuite) TestGetNotFound() { func (suite *JobPublicTestSuite) TestDelete() { tests := []struct { name string + handler http.HandlerFunc + serverURL string id string validateFunc func(error) }{ { name: "when valid UUID returns no error", - id: "550e8400-e29b-41d4-a716-446655440000", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusNoContent) + }, + id: "550e8400-e29b-41d4-a716-446655440000", validateFunc: func(err error) { suite.NoError(err) }, }, { name: "when invalid UUID returns error", - id: "not-a-uuid", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusNoContent) + }, + id: "not-a-uuid", validateFunc: func(err error) { suite.Error(err) suite.Contains(err.Error(), "invalid job ID") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusNoContent) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - err := sut.Job.Delete(suite.ctx, tc.id) - tc.validateFunc(err) - }) - } -} - -func (suite *JobPublicTestSuite) TestDeleteHTTPError() { - tests := []struct { - name string - validateFunc func(error) - }{ { - name: "when HTTP request fails returns error", + name: "when HTTP request fails returns error", + serverURL: "http://127.0.0.1:0", + id: "00000000-0000-0000-0000-000000000000", validateFunc: func(err error) { suite.Error(err) suite.Contains(err.Error(), "delete job") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - err := sut.Job.Delete(suite.ctx, "00000000-0000-0000-0000-000000000000") - tc.validateFunc(err) - }) - } -} - -func (suite *JobPublicTestSuite) TestDeleteNotFound() { - tests := []struct { - name string - validateFunc func(error) - }{ { name: "when server returns 404 returns NotFoundError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"job not found"}`)) + }, + id: "550e8400-e29b-41d4-a716-446655440000", validateFunc: func(err error) { suite.Error(err) @@ -470,22 +322,26 @@ func (suite *JobPublicTestSuite) TestDeleteNotFound() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(`{"error":"job not found"}`)) - }), + var ( + serverURL string + server *httptest.Server ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + } else { + server = httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - err := sut.Job.Delete(suite.ctx, "550e8400-e29b-41d4-a716-446655440000") + err := sut.Job.Delete(suite.ctx, tc.id) tc.validateFunc(err) }) } @@ -494,11 +350,18 @@ func (suite *JobPublicTestSuite) TestDeleteNotFound() { func (suite *JobPublicTestSuite) TestList() { tests := []struct { name string + handler http.HandlerFunc + serverURL string params osapi.ListParams validateFunc func(*osapi.Response[osapi.JobList], error) }{ { - name: "when no filters returns response", + name: "when no filters returns response", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"items":[],"total_items":0}`)) + }, params: osapi.ListParams{}, validateFunc: func(resp *osapi.Response[osapi.JobList], err error) { suite.NoError(err) @@ -509,6 +372,11 @@ func (suite *JobPublicTestSuite) TestList() { }, { name: "when all filters provided returns response", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"items":[],"total_items":0}`)) + }, params: osapi.ListParams{ Status: "completed", Limit: 10, @@ -519,72 +387,24 @@ func (suite *JobPublicTestSuite) TestList() { suite.NotNil(resp) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"items":[],"total_items":0}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.List(suite.ctx, tc.params) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestListHTTPError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobList], error) - }{ { - name: "when HTTP request fails returns error", + name: "when HTTP request fails returns error", + serverURL: "http://127.0.0.1:0", + params: osapi.ListParams{}, validateFunc: func(resp *osapi.Response[osapi.JobList], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "list jobs") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.List(suite.ctx, osapi.ListParams{}) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestListError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobList], error) - }{ { name: "when server returns 401 returns AuthError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) + }, + params: osapi.ListParams{}, validateFunc: func(resp *osapi.Response[osapi.JobList], err error) { suite.Error(err) suite.Nil(resp) @@ -594,38 +414,12 @@ func (suite *JobPublicTestSuite) TestListError() { suite.Equal(http.StatusUnauthorized, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusUnauthorized) - _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.List(suite.ctx, osapi.ListParams{}) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestListNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobList], error) - }{ { name: "when server returns 200 with empty body returns UnexpectedStatusError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, + params: osapi.ListParams{}, validateFunc: func(resp *osapi.Response[osapi.JobList], err error) { suite.Error(err) suite.Nil(resp) @@ -639,20 +433,26 @@ func (suite *JobPublicTestSuite) TestListNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + server *httptest.Server ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + } else { + server = httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Job.List(suite.ctx, osapi.ListParams{}) + resp, err := sut.Job.List(suite.ctx, tc.params) tc.validateFunc(resp, err) }) } @@ -661,82 +461,39 @@ func (suite *JobPublicTestSuite) TestListNilResponse() { func (suite *JobPublicTestSuite) TestQueueStats() { tests := []struct { name string + handler http.HandlerFunc + serverURL string validateFunc func(*osapi.Response[osapi.QueueStats], error) }{ { name: "when requesting queue stats returns response", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"total_jobs":5}`)) + }, validateFunc: func(resp *osapi.Response[osapi.QueueStats], err error) { suite.NoError(err) suite.NotNil(resp) suite.Equal(5, resp.Data.TotalJobs) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"total_jobs":5}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.QueueStats(suite.ctx) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestQueueStatsHTTPError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.QueueStats], error) - }{ { - name: "when HTTP request fails returns error", + name: "when HTTP request fails returns error", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.QueueStats], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "queue stats") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.QueueStats(suite.ctx) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestQueueStatsError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.QueueStats], error) - }{ { name: "when server returns 401 returns AuthError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.QueueStats], err error) { suite.Error(err) suite.Nil(resp) @@ -746,38 +503,11 @@ func (suite *JobPublicTestSuite) TestQueueStatsError() { suite.Equal(http.StatusUnauthorized, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusUnauthorized) - _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.QueueStats(suite.ctx) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestQueueStatsNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.QueueStats], error) - }{ { name: "when server returns 200 with empty body returns UnexpectedStatusError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.QueueStats], err error) { suite.Error(err) suite.Nil(resp) @@ -791,15 +521,21 @@ func (suite *JobPublicTestSuite) TestQueueStatsNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + server *httptest.Server ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + } else { + server = httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) @@ -813,12 +549,23 @@ func (suite *JobPublicTestSuite) TestQueueStatsNilResponse() { func (suite *JobPublicTestSuite) TestRetry() { tests := []struct { name string + handler http.HandlerFunc + serverURL string id string target string validateFunc func(*osapi.Response[osapi.JobCreated], error) }{ { - name: "when valid UUID with empty target returns response", + name: "when valid UUID with empty target returns response", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + _, _ = w.Write( + []byte( + `{"job_id":"550e8400-e29b-41d4-a716-446655440000","status":"pending"}`, + ), + ) + }, id: "550e8400-e29b-41d4-a716-446655440000", target: "", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { @@ -829,7 +576,16 @@ func (suite *JobPublicTestSuite) TestRetry() { }, }, { - name: "when valid UUID with target returns response", + name: "when valid UUID with target returns response", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + _, _ = w.Write( + []byte( + `{"job_id":"550e8400-e29b-41d4-a716-446655440000","status":"pending"}`, + ), + ) + }, id: "550e8400-e29b-41d4-a716-446655440000", target: "web-01", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { @@ -838,7 +594,16 @@ func (suite *JobPublicTestSuite) TestRetry() { }, }, { - name: "when invalid UUID returns error", + name: "when invalid UUID returns error", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + _, _ = w.Write( + []byte( + `{"job_id":"550e8400-e29b-41d4-a716-446655440000","status":"pending"}`, + ), + ) + }, id: "not-a-uuid", target: "", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { @@ -847,80 +612,26 @@ func (suite *JobPublicTestSuite) TestRetry() { suite.Contains(err.Error(), "invalid job ID") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusCreated) - _, _ = w.Write( - []byte( - `{"job_id":"550e8400-e29b-41d4-a716-446655440000","status":"pending"}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Retry(suite.ctx, tc.id, tc.target) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestRetryHTTPError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobCreated], error) - }{ { - name: "when HTTP request fails returns error", + name: "when HTTP request fails returns error", + serverURL: "http://127.0.0.1:0", + id: "00000000-0000-0000-0000-000000000000", + target: "", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "retry job") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Retry( - suite.ctx, - "00000000-0000-0000-0000-000000000000", - "", - ) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestRetryError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobCreated], error) - }{ { name: "when server returns 404 returns NotFoundError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"error":"job not found"}`)) + }, + id: "00000000-0000-0000-0000-000000000000", + target: "", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { suite.Error(err) suite.Nil(resp) @@ -930,42 +641,13 @@ func (suite *JobPublicTestSuite) TestRetryError() { suite.Equal(http.StatusNotFound, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(`{"error":"job not found"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Job.Retry( - suite.ctx, - "00000000-0000-0000-0000-000000000000", - "", - ) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *JobPublicTestSuite) TestRetryNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.JobCreated], error) - }{ { name: "when server returns 201 with empty body returns UnexpectedStatusError", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusCreated) + }, + id: "00000000-0000-0000-0000-000000000000", + target: "", validateFunc: func(resp *osapi.Response[osapi.JobCreated], err error) { suite.Error(err) suite.Nil(resp) @@ -979,24 +661,26 @@ func (suite *JobPublicTestSuite) TestRetryNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusCreated) - }), + var ( + serverURL string + server *httptest.Server ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + } else { + server = httptest.NewServer(tc.handler) + defer server.Close() + serverURL = server.URL + } sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Job.Retry( - suite.ctx, - "00000000-0000-0000-0000-000000000000", - "", - ) + resp, err := sut.Job.Retry(suite.ctx, tc.id, tc.target) tc.validateFunc(resp, err) }) } diff --git a/pkg/osapi/metrics_public_test.go b/pkg/osapi/metrics_public_test.go index ce9ce62..d5df1cb 100644 --- a/pkg/osapi/metrics_public_test.go +++ b/pkg/osapi/metrics_public_test.go @@ -43,122 +43,62 @@ func (suite *MetricsPublicTestSuite) SetupTest() { } func (suite *MetricsPublicTestSuite) TestGet() { + closedServer := httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }), + ) + closedServerURL := closedServer.URL + closedServer.Close() + tests := []struct { name string + handler http.HandlerFunc + serverURL string + ctx context.Context validateFunc func(string, error) }{ { name: "when server returns metrics returns text body", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte("# HELP go_goroutines\n")) + }, + ctx: suite.ctx, validateFunc: func(body string, err error) { suite.NoError(err) suite.Equal("# HELP go_goroutines\n", body) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte("# HELP go_goroutines\n")) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - body, err := sut.Metrics.Get(suite.ctx) - tc.validateFunc(body, err) - }) - } -} - -func (suite *MetricsPublicTestSuite) TestGetErrorStatus() { - tests := []struct { - name string - validateFunc func(string, error) - }{ { name: "when server returns non-200 returns error", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + }, + ctx: suite.ctx, validateFunc: func(body string, err error) { suite.Error(err) suite.Contains(err.Error(), "metrics endpoint returned status") suite.Empty(body) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusInternalServerError) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - body, err := sut.Metrics.Get(suite.ctx) - tc.validateFunc(body, err) - }) - } -} - -func (suite *MetricsPublicTestSuite) TestGetRequestError() { - tests := []struct { - name string - validateFunc func(string, error) - }{ { - name: "when server is unreachable returns error", + name: "when server is unreachable returns error", + serverURL: closedServerURL, + ctx: suite.ctx, validateFunc: func(body string, err error) { suite.Error(err) suite.Contains(err.Error(), "fetching metrics") suite.Empty(body) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), - ) - closedURL := server.URL - server.Close() - - sut := osapi.New( - closedURL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - body, err := sut.Metrics.Get(suite.ctx) - tc.validateFunc(body, err) - }) - } -} - -func (suite *MetricsPublicTestSuite) TestGetCreateRequestError() { - tests := []struct { - name string - validateFunc func(string, error) - }{ { name: "when request creation fails returns error", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, + ctx: nil, validateFunc: func(body string, err error) { suite.Error(err) suite.Contains(err.Error(), "creating metrics request") @@ -169,21 +109,24 @@ func (suite *MetricsPublicTestSuite) TestGetCreateRequestError() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), - ) - defer server.Close() + var targetURL string + + if tc.serverURL != "" { + targetURL = tc.serverURL + } else { + server := httptest.NewServer(tc.handler) + defer server.Close() + targetURL = server.URL + } sut := osapi.New( - server.URL, + targetURL, "test-token", osapi.WithLogger(slog.Default()), ) //nolint:staticcheck // nil context intentionally triggers NewRequestWithContext error - body, err := sut.Metrics.Get(nil) + body, err := sut.Metrics.Get(tc.ctx) tc.validateFunc(body, err) }) } diff --git a/pkg/osapi/node_public_test.go b/pkg/osapi/node_public_test.go index e4752d9..63e3a30 100644 --- a/pkg/osapi/node_public_test.go +++ b/pkg/osapi/node_public_test.go @@ -46,12 +46,23 @@ func (suite *NodePublicTestSuite) SetupTest() { func (suite *NodePublicTestSuite) TestHostname() { tests := []struct { name string + handler http.HandlerFunc + serverURL string target string validateFunc func(*osapi.Response[osapi.Collection[osapi.HostnameResult]], error) }{ { name: "when requesting hostname returns results", target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write( + []byte( + `{"job_id":"00000000-0000-0000-0000-000000000001","results":[{"hostname":"test-host"}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.HostnameResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -60,145 +71,75 @@ func (suite *NodePublicTestSuite) TestHostname() { suite.Equal("test-host", resp.Data.Results[0].Hostname) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write( - []byte( - `{"job_id":"00000000-0000-0000-0000-000000000001","results":[{"hostname":"test-host"}]}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Hostname(suite.ctx, tc.target) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestHostnameClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.HostnameResult]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when server returns 403 returns AuthError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.HostnameResult]], err error) { suite.Error(err) suite.Nil(resp) - suite.Contains(err.Error(), "get hostname") + + var target *osapi.AuthError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusForbidden, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Hostname(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestHostnameNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.HostnameResult]], error) - }{ { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + name: "when client HTTP call fails returns error", + target: "_any", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.HostnameResult]], err error) { suite.Error(err) suite.Nil(resp) - - var target *osapi.UnexpectedStatusError - suite.True(errors.As(err, &target)) - suite.Equal(http.StatusOK, target.StatusCode) - suite.Equal("nil response body", target.Message) + suite.Contains(err.Error(), "get hostname") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Hostname(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestHostnameError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.HostnameResult]], error) - }{ { - name: "when server returns 403 returns AuthError", + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.HostnameResult]], err error) { suite.Error(err) suite.Nil(resp) - var target *osapi.AuthError + var target *osapi.UnexpectedStatusError suite.True(errors.As(err, &target)) - suite.Equal(http.StatusForbidden, target.StatusCode) + suite.Equal(http.StatusOK, target.StatusCode) + suite.Equal("nil response body", target.Message) }, }, } for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Hostname(suite.ctx, "_any") + resp, err := sut.Node.Hostname(suite.ctx, tc.target) tc.validateFunc(resp, err) }) } @@ -207,12 +148,19 @@ func (suite *NodePublicTestSuite) TestHostnameError() { func (suite *NodePublicTestSuite) TestStatus() { tests := []struct { name string + handler http.HandlerFunc + serverURL string target string validateFunc func(*osapi.Response[osapi.Collection[osapi.NodeStatus]], error) }{ { name: "when requesting status returns results", target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"results":[{"hostname":"web-01"}]}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.NodeStatus]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -220,38 +168,14 @@ func (suite *NodePublicTestSuite) TestStatus() { suite.Equal("web-01", resp.Data.Results[0].Hostname) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"results":[{"hostname":"web-01"}]}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Status(suite.ctx, tc.target) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestStatusError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.NodeStatus]], error) - }{ { - name: "when server returns 403 returns AuthError", + name: "when server returns 403 returns AuthError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.NodeStatus]], err error) { suite.Error(err) suite.Nil(resp) @@ -261,72 +185,22 @@ func (suite *NodePublicTestSuite) TestStatusError() { suite.Equal(http.StatusForbidden, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Status(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestStatusClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.NodeStatus]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when client HTTP call fails returns error", + target: "_any", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.NodeStatus]], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "get status") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Status(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestStatusNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.NodeStatus]], error) - }{ { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.NodeStatus]], err error) { suite.Error(err) suite.Nil(resp) @@ -341,20 +215,28 @@ func (suite *NodePublicTestSuite) TestStatusNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Status(suite.ctx, "_any") + resp, err := sut.Node.Status(suite.ctx, tc.target) tc.validateFunc(resp, err) }) } @@ -363,12 +245,19 @@ func (suite *NodePublicTestSuite) TestStatusNilResponse() { func (suite *NodePublicTestSuite) TestDisk() { tests := []struct { name string + handler http.HandlerFunc + serverURL string target string validateFunc func(*osapi.Response[osapi.Collection[osapi.DiskResult]], error) }{ { name: "when requesting disk returns results", target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"results":[{"hostname":"disk-host"}]}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DiskResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -376,38 +265,14 @@ func (suite *NodePublicTestSuite) TestDisk() { suite.Equal("disk-host", resp.Data.Results[0].Hostname) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"results":[{"hostname":"disk-host"}]}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Disk(suite.ctx, tc.target) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestDiskError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DiskResult]], error) - }{ { - name: "when server returns 403 returns AuthError", + name: "when server returns 403 returns AuthError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DiskResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -417,72 +282,22 @@ func (suite *NodePublicTestSuite) TestDiskError() { suite.Equal(http.StatusForbidden, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Disk(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestDiskClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DiskResult]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when client HTTP call fails returns error", + target: "_any", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DiskResult]], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "get disk") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Disk(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestDiskNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DiskResult]], error) - }{ { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DiskResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -497,20 +312,28 @@ func (suite *NodePublicTestSuite) TestDiskNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Disk(suite.ctx, "_any") + resp, err := sut.Node.Disk(suite.ctx, tc.target) tc.validateFunc(resp, err) }) } @@ -519,12 +342,19 @@ func (suite *NodePublicTestSuite) TestDiskNilResponse() { func (suite *NodePublicTestSuite) TestMemory() { tests := []struct { name string + handler http.HandlerFunc + serverURL string target string validateFunc func(*osapi.Response[osapi.Collection[osapi.MemoryResult]], error) }{ { name: "when requesting memory returns results", target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"results":[{"hostname":"mem-host"}]}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.MemoryResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -532,21 +362,70 @@ func (suite *NodePublicTestSuite) TestMemory() { suite.Equal("mem-host", resp.Data.Results[0].Hostname) }, }, + { + name: "when server returns 403 returns AuthError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, + validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.MemoryResult]], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.AuthError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusForbidden, target.StatusCode) + }, + }, + { + name: "when client HTTP call fails returns error", + target: "_any", + serverURL: "http://127.0.0.1:0", + validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.MemoryResult]], err error) { + suite.Error(err) + suite.Nil(resp) + suite.Contains(err.Error(), "get memory") + }, + }, + { + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, + validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.MemoryResult]], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.UnexpectedStatusError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusOK, target.StatusCode) + suite.Equal("nil response body", target.Message) + }, + }, } for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"results":[{"hostname":"mem-host"}]}`)) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) @@ -557,130 +436,22 @@ func (suite *NodePublicTestSuite) TestMemory() { } } -func (suite *NodePublicTestSuite) TestMemoryError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.MemoryResult]], error) - }{ - { - name: "when server returns 403 returns AuthError", - validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.MemoryResult]], err error) { - suite.Error(err) - suite.Nil(resp) - - var target *osapi.AuthError - suite.True(errors.As(err, &target)) - suite.Equal(http.StatusForbidden, target.StatusCode) - }, - }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Memory(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestMemoryClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.MemoryResult]], error) - }{ - { - name: "when client HTTP call fails returns error", - validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.MemoryResult]], err error) { - suite.Error(err) - suite.Nil(resp) - suite.Contains(err.Error(), "get memory") - }, - }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Memory(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestMemoryNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.MemoryResult]], error) - }{ - { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", - validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.MemoryResult]], err error) { - suite.Error(err) - suite.Nil(resp) - - var target *osapi.UnexpectedStatusError - suite.True(errors.As(err, &target)) - suite.Equal(http.StatusOK, target.StatusCode) - suite.Equal("nil response body", target.Message) - }, - }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Memory(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestLoad() { +func (suite *NodePublicTestSuite) TestLoad() { tests := []struct { name string + handler http.HandlerFunc + serverURL string target string validateFunc func(*osapi.Response[osapi.Collection[osapi.LoadResult]], error) }{ { name: "when requesting load returns results", target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"results":[{"hostname":"load-host"}]}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.LoadResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -688,38 +459,14 @@ func (suite *NodePublicTestSuite) TestLoad() { suite.Equal("load-host", resp.Data.Results[0].Hostname) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"results":[{"hostname":"load-host"}]}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Load(suite.ctx, tc.target) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestLoadError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.LoadResult]], error) - }{ { - name: "when server returns 403 returns AuthError", + name: "when server returns 403 returns AuthError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.LoadResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -729,72 +476,22 @@ func (suite *NodePublicTestSuite) TestLoadError() { suite.Equal(http.StatusForbidden, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Load(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestLoadClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.LoadResult]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when client HTTP call fails returns error", + target: "_any", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.LoadResult]], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "get load") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Load(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestLoadNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.LoadResult]], error) - }{ { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.LoadResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -809,20 +506,28 @@ func (suite *NodePublicTestSuite) TestLoadNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Load(suite.ctx, "_any") + resp, err := sut.Node.Load(suite.ctx, tc.target) tc.validateFunc(resp, err) }) } @@ -831,12 +536,19 @@ func (suite *NodePublicTestSuite) TestLoadNilResponse() { func (suite *NodePublicTestSuite) TestOS() { tests := []struct { name string + handler http.HandlerFunc + serverURL string target string validateFunc func(*osapi.Response[osapi.Collection[osapi.OSInfoResult]], error) }{ { name: "when requesting OS info returns results", target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{"results":[{"hostname":"os-host"}]}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.OSInfoResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -844,38 +556,14 @@ func (suite *NodePublicTestSuite) TestOS() { suite.Equal("os-host", resp.Data.Results[0].Hostname) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"results":[{"hostname":"os-host"}]}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.OS(suite.ctx, tc.target) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestOSError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.OSInfoResult]], error) - }{ { - name: "when server returns 403 returns AuthError", + name: "when server returns 403 returns AuthError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.OSInfoResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -885,72 +573,22 @@ func (suite *NodePublicTestSuite) TestOSError() { suite.Equal(http.StatusForbidden, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.OS(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestOSClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.OSInfoResult]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when client HTTP call fails returns error", + target: "_any", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.OSInfoResult]], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "get os") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.OS(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestOSNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.OSInfoResult]], error) - }{ { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.OSInfoResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -965,20 +603,28 @@ func (suite *NodePublicTestSuite) TestOSNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.OS(suite.ctx, "_any") + resp, err := sut.Node.OS(suite.ctx, tc.target) tc.validateFunc(resp, err) }) } @@ -987,12 +633,21 @@ func (suite *NodePublicTestSuite) TestOSNilResponse() { func (suite *NodePublicTestSuite) TestUptime() { tests := []struct { name string + handler http.HandlerFunc + serverURL string target string validateFunc func(*osapi.Response[osapi.Collection[osapi.UptimeResult]], error) }{ { name: "when requesting uptime returns results", target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write( + []byte(`{"results":[{"hostname":"uptime-host","uptime":"2d3h"}]}`), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.UptimeResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -1001,115 +656,39 @@ func (suite *NodePublicTestSuite) TestUptime() { suite.Equal("2d3h", resp.Data.Results[0].Uptime) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write( - []byte(`{"results":[{"hostname":"uptime-host","uptime":"2d3h"}]}`), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Uptime(suite.ctx, tc.target) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestUptimeError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.UptimeResult]], error) - }{ { - name: "when server returns 403 returns AuthError", - validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.UptimeResult]], err error) { - suite.Error(err) - suite.Nil(resp) - - var target *osapi.AuthError - suite.True(errors.As(err, &target)) - suite.Equal(http.StatusForbidden, target.StatusCode) + name: "when server returns 403 returns AuthError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) }, - }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Uptime(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestUptimeClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.UptimeResult]], error) - }{ - { - name: "when client HTTP call fails returns error", validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.UptimeResult]], err error) { suite.Error(err) suite.Nil(resp) - suite.Contains(err.Error(), "get uptime") - }, - }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Uptime(suite.ctx, "_any") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestUptimeNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.UptimeResult]], error) - }{ + + var target *osapi.AuthError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusForbidden, target.StatusCode) + }, + }, + { + name: "when client HTTP call fails returns error", + target: "_any", + serverURL: "http://127.0.0.1:0", + validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.UptimeResult]], err error) { + suite.Error(err) + suite.Nil(resp) + suite.Contains(err.Error(), "get uptime") + }, + }, { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.UptimeResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -1124,20 +703,28 @@ func (suite *NodePublicTestSuite) TestUptimeNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Uptime(suite.ctx, "_any") + resp, err := sut.Node.Uptime(suite.ctx, tc.target) tc.validateFunc(resp, err) }) } @@ -1145,15 +732,24 @@ func (suite *NodePublicTestSuite) TestUptimeNilResponse() { func (suite *NodePublicTestSuite) TestGetDNS() { tests := []struct { - name string - target string - iface string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DNSConfig]], error) + name string + handler http.HandlerFunc + serverURL string + target string + interfaceName string + validateFunc func(*osapi.Response[osapi.Collection[osapi.DNSConfig]], error) }{ { - name: "when requesting DNS returns results", - target: "_any", - iface: "eth0", + name: "when requesting DNS returns results", + target: "_any", + interfaceName: "eth0", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write( + []byte(`{"results":[{"hostname":"dns-host","servers":["8.8.8.8"]}]}`), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSConfig]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -1162,40 +758,15 @@ func (suite *NodePublicTestSuite) TestGetDNS() { suite.Equal([]string{"8.8.8.8"}, resp.Data.Results[0].Servers) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write( - []byte(`{"results":[{"hostname":"dns-host","servers":["8.8.8.8"]}]}`), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.GetDNS(suite.ctx, tc.target, tc.iface) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestGetDNSError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DNSConfig]], error) - }{ { - name: "when server returns 403 returns AuthError", + name: "when server returns 403 returns AuthError", + target: "_any", + interfaceName: "eth0", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSConfig]], err error) { suite.Error(err) suite.Nil(resp) @@ -1205,72 +776,24 @@ func (suite *NodePublicTestSuite) TestGetDNSError() { suite.Equal(http.StatusForbidden, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.GetDNS(suite.ctx, "_any", "eth0") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestGetDNSClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DNSConfig]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when client HTTP call fails returns error", + target: "_any", + interfaceName: "eth0", + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSConfig]], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "get dns") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.GetDNS(suite.ctx, "_any", "eth0") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestGetDNSNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DNSConfig]], error) - }{ { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + interfaceName: "eth0", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSConfig]], err error) { suite.Error(err) suite.Nil(resp) @@ -1285,20 +808,28 @@ func (suite *NodePublicTestSuite) TestGetDNSNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.GetDNS(suite.ctx, "_any", "eth0") + resp, err := sut.Node.GetDNS(suite.ctx, tc.target, tc.interfaceName) tc.validateFunc(resp, err) }) } @@ -1307,6 +838,8 @@ func (suite *NodePublicTestSuite) TestGetDNSNilResponse() { func (suite *NodePublicTestSuite) TestUpdateDNS() { tests := []struct { name string + handler http.HandlerFunc + serverURL string target string iface string servers []string @@ -1319,6 +852,15 @@ func (suite *NodePublicTestSuite) TestUpdateDNS() { iface: "eth0", servers: []string{"8.8.8.8", "8.8.4.4"}, searchDomains: nil, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"dns-host","status":"completed","changed":true}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -1334,6 +876,15 @@ func (suite *NodePublicTestSuite) TestUpdateDNS() { iface: "eth0", servers: nil, searchDomains: []string{"example.com"}, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"dns-host","status":"completed","changed":true}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -1345,6 +896,15 @@ func (suite *NodePublicTestSuite) TestUpdateDNS() { iface: "eth0", servers: []string{"8.8.8.8"}, searchDomains: []string{"example.com"}, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"dns-host","status":"completed","changed":true}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -1356,53 +916,30 @@ func (suite *NodePublicTestSuite) TestUpdateDNS() { iface: "eth0", servers: nil, searchDomains: nil, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"dns-host","status":"completed","changed":true}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], err error) { suite.NoError(err) suite.NotNil(resp) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusAccepted) - _, _ = w.Write( - []byte( - `{"results":[{"hostname":"dns-host","status":"completed","changed":true}]}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.UpdateDNS( - suite.ctx, - tc.target, - tc.iface, - tc.servers, - tc.searchDomains, - ) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestUpdateDNSError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], error) - }{ { - name: "when server returns 403 returns AuthError", + name: "when server returns 403 returns AuthError", + target: "_any", + iface: "eth0", + servers: []string{"8.8.8.8"}, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -1412,235 +949,139 @@ func (suite *NodePublicTestSuite) TestUpdateDNSError() { suite.Equal(http.StatusForbidden, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.UpdateDNS(suite.ctx, "_any", "eth0", []string{"8.8.8.8"}, nil) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestUpdateDNSClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when client HTTP call fails returns error", + target: "_any", + iface: "eth0", + servers: []string{"8.8.8.8"}, + serverURL: "http://127.0.0.1:0", validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], err error) { suite.Error(err) suite.Nil(resp) suite.Contains(err.Error(), "update dns") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.UpdateDNS(suite.ctx, "_any", "eth0", []string{"8.8.8.8"}, nil) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestUpdateDNSNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], error) - }{ - { - name: "when server returns 202 with no JSON body returns UnexpectedStatusError", - validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], err error) { - suite.Error(err) - suite.Nil(resp) - - var target *osapi.UnexpectedStatusError - suite.True(errors.As(err, &target)) - suite.Equal(http.StatusAccepted, target.StatusCode) - suite.Equal("nil response body", target.Message) - }, - }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusAccepted) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.UpdateDNS(suite.ctx, "_any", "eth0", []string{"8.8.8.8"}, nil) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestPing() { - tests := []struct { - name string - target string - address string - validateFunc func(*osapi.Response[osapi.Collection[osapi.PingResult]], error) - }{ - { - name: "when pinging address returns results", - target: "_any", - address: "8.8.8.8", - validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.PingResult]], err error) { - suite.NoError(err) - suite.NotNil(resp) - suite.Len(resp.Data.Results, 1) - suite.Equal("ping-host", resp.Data.Results[0].Hostname) - suite.Equal(4, resp.Data.Results[0].PacketsSent) - }, - }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, _ = w.Write( - []byte( - `{"results":[{"hostname":"ping-host","packets_sent":4,"packets_received":4,"packet_loss":0.0}]}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Ping(suite.ctx, tc.target, tc.address) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestPingError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.PingResult]], error) - }{ - { - name: "when server returns 403 returns AuthError", - validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.PingResult]], err error) { - suite.Error(err) - suite.Nil(resp) - - var target *osapi.AuthError - suite.True(errors.As(err, &target)) - suite.Equal(http.StatusForbidden, target.StatusCode) - }, - }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusForbidden) - _, _ = w.Write([]byte(`{"error":"forbidden"}`)) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Ping(suite.ctx, "_any", "8.8.8.8") - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestPingClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.PingResult]], error) - }{ { - name: "when client HTTP call fails returns error", - validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.PingResult]], err error) { + name: "when server returns 202 with no JSON body returns UnexpectedStatusError", + target: "_any", + iface: "eth0", + servers: []string{"8.8.8.8"}, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusAccepted) + }, + validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.DNSUpdateResult]], err error) { suite.Error(err) suite.Nil(resp) - suite.Contains(err.Error(), "ping") + + var target *osapi.UnexpectedStatusError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusAccepted, target.StatusCode) + suite.Equal("nil response body", target.Message) }, }, } for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), + var ( + serverURL string + cleanup func() ) - server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Ping(suite.ctx, "_any", "8.8.8.8") + resp, err := sut.Node.UpdateDNS( + suite.ctx, + tc.target, + tc.iface, + tc.servers, + tc.searchDomains, + ) tc.validateFunc(resp, err) }) } } -func (suite *NodePublicTestSuite) TestPingNilResponse() { +func (suite *NodePublicTestSuite) TestPing() { tests := []struct { name string + handler http.HandlerFunc + serverURL string + target string + address string validateFunc func(*osapi.Response[osapi.Collection[osapi.PingResult]], error) }{ { - name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + name: "when pinging address returns results", + target: "_any", + address: "8.8.8.8", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"ping-host","packets_sent":4,"packets_received":4,"packet_loss":0.0}]}`, + ), + ) + }, + validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.PingResult]], err error) { + suite.NoError(err) + suite.NotNil(resp) + suite.Len(resp.Data.Results, 1) + suite.Equal("ping-host", resp.Data.Results[0].Hostname) + suite.Equal(4, resp.Data.Results[0].PacketsSent) + }, + }, + { + name: "when server returns 403 returns AuthError", + target: "_any", + address: "8.8.8.8", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusForbidden) + _, _ = w.Write([]byte(`{"error":"forbidden"}`)) + }, + validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.PingResult]], err error) { + suite.Error(err) + suite.Nil(resp) + + var target *osapi.AuthError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusForbidden, target.StatusCode) + }, + }, + { + name: "when client HTTP call fails returns error", + target: "_any", + address: "8.8.8.8", + serverURL: "http://127.0.0.1:0", + validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.PingResult]], err error) { + suite.Error(err) + suite.Nil(resp) + suite.Contains(err.Error(), "ping") + }, + }, + { + name: "when server returns 200 with no JSON body returns UnexpectedStatusError", + target: "_any", + address: "8.8.8.8", + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.PingResult]], err error) { suite.Error(err) suite.Nil(resp) @@ -1655,20 +1096,28 @@ func (suite *NodePublicTestSuite) TestPingNilResponse() { for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusOK) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Ping(suite.ctx, "_any", "8.8.8.8") + resp, err := sut.Node.Ping(suite.ctx, tc.target, tc.address) tc.validateFunc(resp, err) }) } @@ -1677,6 +1126,8 @@ func (suite *NodePublicTestSuite) TestPingNilResponse() { func (suite *NodePublicTestSuite) TestExec() { tests := []struct { name string + handler http.HandlerFunc + serverURL string req osapi.ExecRequest validateFunc func(*osapi.Response[osapi.Collection[osapi.CommandResult]], error) }{ @@ -1686,6 +1137,15 @@ func (suite *NodePublicTestSuite) TestExec() { Command: "whoami", Target: "_any", }, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"exec-host","stdout":"root\n","exit_code":0,"changed":true}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -1704,158 +1164,97 @@ func (suite *NodePublicTestSuite) TestExec() { Timeout: 10, Target: "_any", }, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"exec-host","stdout":"root\n","exit_code":0,"changed":true}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.NoError(err) suite.NotNil(resp) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusAccepted) - _, _ = w.Write( - []byte( - `{"results":[{"hostname":"exec-host","stdout":"root\n","exit_code":0,"changed":true}]}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Exec(suite.ctx, tc.req) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestExecClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.CommandResult]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when server returns 400 returns ValidationError", + req: osapi.ExecRequest{ + Target: "_any", + }, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + _, _ = w.Write([]byte(`{"error":"command is required"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.Error(err) suite.Nil(resp) - suite.Contains(err.Error(), "exec command") + + var target *osapi.ValidationError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusBadRequest, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Exec(suite.ctx, osapi.ExecRequest{ + { + name: "when client HTTP call fails returns error", + serverURL: "http://127.0.0.1:0", + req: osapi.ExecRequest{ Command: "whoami", Target: "_any", - }) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestExecNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.CommandResult]], error) - }{ - { - name: "when server returns 202 with no JSON body returns UnexpectedStatusError", + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.Error(err) suite.Nil(resp) - - var target *osapi.UnexpectedStatusError - suite.True(errors.As(err, &target)) - suite.Equal(http.StatusAccepted, target.StatusCode) - suite.Equal("nil response body", target.Message) + suite.Contains(err.Error(), "exec command") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusAccepted) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Exec(suite.ctx, osapi.ExecRequest{ + { + name: "when server returns 202 with no JSON body returns UnexpectedStatusError", + req: osapi.ExecRequest{ Command: "whoami", Target: "_any", - }) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestExecError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.CommandResult]], error) - }{ - { - name: "when server returns 400 returns ValidationError", + }, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusAccepted) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.Error(err) suite.Nil(resp) - var target *osapi.ValidationError + var target *osapi.UnexpectedStatusError suite.True(errors.As(err, &target)) - suite.Equal(http.StatusBadRequest, target.StatusCode) + suite.Equal(http.StatusAccepted, target.StatusCode) + suite.Equal("nil response body", target.Message) }, }, } for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusBadRequest) - _, _ = w.Write([]byte(`{"error":"command is required"}`)) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Exec(suite.ctx, osapi.ExecRequest{ - Target: "_any", - }) + resp, err := sut.Node.Exec(suite.ctx, tc.req) tc.validateFunc(resp, err) }) } @@ -1864,6 +1263,8 @@ func (suite *NodePublicTestSuite) TestExecError() { func (suite *NodePublicTestSuite) TestShell() { tests := []struct { name string + handler http.HandlerFunc + serverURL string req osapi.ShellRequest validateFunc func(*osapi.Response[osapi.Collection[osapi.CommandResult]], error) }{ @@ -1873,6 +1274,15 @@ func (suite *NodePublicTestSuite) TestShell() { Command: "uname -a", Target: "_any", }, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"shell-host","exit_code":0,"changed":false}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.NoError(err) suite.NotNil(resp) @@ -1888,158 +1298,97 @@ func (suite *NodePublicTestSuite) TestShell() { Timeout: 15, Target: "_any", }, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _, _ = w.Write( + []byte( + `{"results":[{"hostname":"shell-host","exit_code":0,"changed":false}]}`, + ), + ) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.NoError(err) suite.NotNil(resp) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusAccepted) - _, _ = w.Write( - []byte( - `{"results":[{"hostname":"shell-host","exit_code":0,"changed":false}]}`, - ), - ) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Shell(suite.ctx, tc.req) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestShellClientError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.CommandResult]], error) - }{ { - name: "when client HTTP call fails returns error", + name: "when server returns 400 returns ValidationError", + req: osapi.ShellRequest{ + Target: "_any", + }, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + _, _ = w.Write([]byte(`{"error":"command is required"}`)) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.Error(err) suite.Nil(resp) - suite.Contains(err.Error(), "shell command") + + var target *osapi.ValidationError + suite.True(errors.As(err, &target)) + suite.Equal(http.StatusBadRequest, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}), - ) - server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Shell(suite.ctx, osapi.ShellRequest{ + { + name: "when client HTTP call fails returns error", + serverURL: "http://127.0.0.1:0", + req: osapi.ShellRequest{ Command: "uname -a", Target: "_any", - }) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestShellNilResponse() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.CommandResult]], error) - }{ - { - name: "when server returns 202 with no JSON body returns UnexpectedStatusError", + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.Error(err) suite.Nil(resp) - - var target *osapi.UnexpectedStatusError - suite.True(errors.As(err, &target)) - suite.Equal(http.StatusAccepted, target.StatusCode) - suite.Equal("nil response body", target.Message) + suite.Contains(err.Error(), "shell command") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusAccepted) - }), - ) - defer server.Close() - - sut := osapi.New( - server.URL, - "test-token", - osapi.WithLogger(slog.Default()), - ) - - resp, err := sut.Node.Shell(suite.ctx, osapi.ShellRequest{ + { + name: "when server returns 202 with no JSON body returns UnexpectedStatusError", + req: osapi.ShellRequest{ Command: "uname -a", Target: "_any", - }) - tc.validateFunc(resp, err) - }) - } -} - -func (suite *NodePublicTestSuite) TestShellError() { - tests := []struct { - name string - validateFunc func(*osapi.Response[osapi.Collection[osapi.CommandResult]], error) - }{ - { - name: "when server returns 400 returns ValidationError", + }, + handler: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusAccepted) + }, validateFunc: func(resp *osapi.Response[osapi.Collection[osapi.CommandResult]], err error) { suite.Error(err) suite.Nil(resp) - var target *osapi.ValidationError + var target *osapi.UnexpectedStatusError suite.True(errors.As(err, &target)) - suite.Equal(http.StatusBadRequest, target.StatusCode) + suite.Equal(http.StatusAccepted, target.StatusCode) + suite.Equal("nil response body", target.Message) }, }, } for _, tc := range tests { suite.Run(tc.name, func() { - server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusBadRequest) - _, _ = w.Write([]byte(`{"error":"command is required"}`)) - }), + var ( + serverURL string + cleanup func() ) - defer server.Close() + + if tc.serverURL != "" { + serverURL = tc.serverURL + cleanup = func() {} + } else { + server := httptest.NewServer(tc.handler) + serverURL = server.URL + cleanup = server.Close + } + defer cleanup() sut := osapi.New( - server.URL, + serverURL, "test-token", osapi.WithLogger(slog.Default()), ) - resp, err := sut.Node.Shell(suite.ctx, osapi.ShellRequest{ - Target: "_any", - }) + resp, err := sut.Node.Shell(suite.ctx, tc.req) tc.validateFunc(resp, err) }) } diff --git a/pkg/osapi/osapi_public_test.go b/pkg/osapi/osapi_public_test.go index fc1f1e3..188283b 100644 --- a/pkg/osapi/osapi_public_test.go +++ b/pkg/osapi/osapi_public_test.go @@ -54,10 +54,14 @@ func (suite *ClientPublicTestSuite) TearDownTest() { func (suite *ClientPublicTestSuite) TestNew() { tests := []struct { name string + opts func() []osapi.Option validateFunc func(*osapi.Client) }{ { name: "when creating client returns all services", + opts: func() []osapi.Option { + return nil + }, validateFunc: func(c *osapi.Client) { suite.NotNil(c) suite.NotNil(c.Node) @@ -67,23 +71,14 @@ func (suite *ClientPublicTestSuite) TestNew() { suite.NotNil(c.Metrics) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - c := osapi.New(suite.server.URL, "test-token") - tc.validateFunc(c) - }) - } -} - -func (suite *ClientPublicTestSuite) TestNewWithHTTPTransport() { - tests := []struct { - name string - validateFunc func(*osapi.Client) - }{ { name: "when custom transport provided creates client", + opts: func() []osapi.Option { + return []osapi.Option{ + osapi.WithHTTPTransport(&http.Transport{}), + osapi.WithLogger(slog.Default()), + } + }, validateFunc: func(c *osapi.Client) { suite.NotNil(c) }, @@ -92,18 +87,14 @@ func (suite *ClientPublicTestSuite) TestNewWithHTTPTransport() { for _, tc := range tests { suite.Run(tc.name, func() { - customTransport := &http.Transport{} - c := osapi.New( - suite.server.URL, - "test-token", - osapi.WithHTTPTransport(customTransport), - osapi.WithLogger(slog.Default()), - ) + c := osapi.New(suite.server.URL, "test-token", tc.opts()...) tc.validateFunc(c) }) } } -func TestClientPublicTestSuite(t *testing.T) { +func TestClientPublicTestSuite( + t *testing.T, +) { suite.Run(t, new(ClientPublicTestSuite)) } diff --git a/pkg/osapi/response_test.go b/pkg/osapi/response_test.go index 9cba2fa..3d14331 100644 --- a/pkg/osapi/response_test.go +++ b/pkg/osapi/response_test.go @@ -33,73 +33,55 @@ type ResponseTestSuite struct { suite.Suite } -func (suite *ResponseTestSuite) TestCheckErrorSuccess() { +func (suite *ResponseTestSuite) TestCheckError() { tests := []struct { - name string - statusCode int + name string + statusCode int + validateFunc func(error) }{ { name: "when status is 200", statusCode: 200, + validateFunc: func(err error) { + suite.NoError(err) + }, }, { name: "when status is 201", statusCode: 201, + validateFunc: func(err error) { + suite.NoError(err) + }, }, { name: "when status is 202", statusCode: 202, + validateFunc: func(err error) { + suite.NoError(err) + }, }, { name: "when status is 204", statusCode: 204, + validateFunc: func(err error) { + suite.NoError(err) + }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - err := checkError(tc.statusCode) - suite.NoError(err) - }) - } -} - -func (suite *ResponseTestSuite) TestCheckErrorValidation() { - tests := []struct { - name string - statusCode int - validateFunc func(error) - }{ { name: "when status is 400", statusCode: 400, validateFunc: func(err error) { + suite.Error(err) var target *ValidationError suite.True(errors.As(err, &target)) suite.Equal(400, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - err := checkError(tc.statusCode) - suite.Error(err) - tc.validateFunc(err) - }) - } -} - -func (suite *ResponseTestSuite) TestCheckErrorAuth() { - tests := []struct { - name string - statusCode int - validateFunc func(error) - }{ { name: "when status is 401", statusCode: 401, validateFunc: func(err error) { + suite.Error(err) var target *AuthError suite.True(errors.As(err, &target)) suite.Equal(401, target.StatusCode) @@ -109,110 +91,47 @@ func (suite *ResponseTestSuite) TestCheckErrorAuth() { name: "when status is 403", statusCode: 403, validateFunc: func(err error) { + suite.Error(err) var target *AuthError suite.True(errors.As(err, &target)) suite.Equal(403, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - err := checkError(tc.statusCode) - suite.Error(err) - tc.validateFunc(err) - }) - } -} - -func (suite *ResponseTestSuite) TestCheckErrorNotFound() { - tests := []struct { - name string - statusCode int - validateFunc func(error) - }{ { name: "when status is 404", statusCode: 404, validateFunc: func(err error) { + suite.Error(err) var target *NotFoundError suite.True(errors.As(err, &target)) suite.Equal(404, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - err := checkError(tc.statusCode) - suite.Error(err) - tc.validateFunc(err) - }) - } -} - -func (suite *ResponseTestSuite) TestCheckErrorConflict() { - tests := []struct { - name string - statusCode int - validateFunc func(error) - }{ { name: "when status is 409", statusCode: 409, validateFunc: func(err error) { + suite.Error(err) var target *ConflictError suite.True(errors.As(err, &target)) suite.Equal(409, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - err := checkError(tc.statusCode) - suite.Error(err) - tc.validateFunc(err) - }) - } -} - -func (suite *ResponseTestSuite) TestCheckErrorServer() { - tests := []struct { - name string - statusCode int - validateFunc func(error) - }{ { name: "when status is 500", statusCode: 500, validateFunc: func(err error) { + suite.Error(err) var target *ServerError suite.True(errors.As(err, &target)) suite.Equal(500, target.StatusCode) }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - err := checkError(tc.statusCode) - suite.Error(err) - tc.validateFunc(err) - }) - } -} - -func (suite *ResponseTestSuite) TestCheckErrorUnexpected() { - tests := []struct { - name string - statusCode int - validateFunc func(error) - }{ { name: "when status is 503", statusCode: 503, validateFunc: func(err error) { + suite.Error(err) var target *UnexpectedStatusError suite.True(errors.As(err, &target)) suite.Equal(503, target.StatusCode) @@ -223,13 +142,12 @@ func (suite *ResponseTestSuite) TestCheckErrorUnexpected() { for _, tc := range tests { suite.Run(tc.name, func() { err := checkError(tc.statusCode) - suite.Error(err) tc.validateFunc(err) }) } } -func (suite *ResponseTestSuite) TestCheckErrorWithMessage() { +func (suite *ResponseTestSuite) TestCheckErrorMessages() { tests := []struct { name string statusCode int @@ -244,32 +162,16 @@ func (suite *ResponseTestSuite) TestCheckErrorWithMessage() { return []*gen.ErrorResponse{{Error: &msg}} }(), validateFunc: func(err error) { + suite.Error(err) suite.Contains(err.Error(), "field 'name' is required") }, }, - } - - for _, tc := range tests { - suite.Run(tc.name, func() { - err := checkError(tc.statusCode, tc.responses...) - suite.Error(err) - tc.validateFunc(err) - }) - } -} - -func (suite *ResponseTestSuite) TestCheckErrorNilResponses() { - tests := []struct { - name string - statusCode int - responses []*gen.ErrorResponse - validateFunc func(error) - }{ { name: "when all responses are nil", statusCode: 400, responses: []*gen.ErrorResponse{nil, nil}, validateFunc: func(err error) { + suite.Error(err) suite.Contains(err.Error(), "unexpected status 400") }, }, @@ -278,6 +180,7 @@ func (suite *ResponseTestSuite) TestCheckErrorNilResponses() { statusCode: 500, responses: nil, validateFunc: func(err error) { + suite.Error(err) suite.Contains(err.Error(), "unexpected status 500") }, }, @@ -286,6 +189,7 @@ func (suite *ResponseTestSuite) TestCheckErrorNilResponses() { statusCode: 404, responses: []*gen.ErrorResponse{{Error: nil}}, validateFunc: func(err error) { + suite.Error(err) suite.Contains(err.Error(), "unexpected status 404") }, }, @@ -294,7 +198,6 @@ func (suite *ResponseTestSuite) TestCheckErrorNilResponses() { for _, tc := range tests { suite.Run(tc.name, func() { err := checkError(tc.statusCode, tc.responses...) - suite.Error(err) tc.validateFunc(err) }) }