Replace ErrorResponse with SlurmAPIError that extracts structured errors/warnings from JSON body when Slurm returns non-2xx (e.g. 404 with valid JSON). Add IsNotFound helper for fallback logic. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
86 lines
2.2 KiB
Go
86 lines
2.2 KiB
Go
package slurm
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
// errorResponseFields is used to parse errors/warnings from a Slurm API error body.
|
|
type errorResponseFields struct {
|
|
Errors OpenapiErrors `json:"errors,omitempty"`
|
|
Warnings OpenapiWarnings `json:"warnings,omitempty"`
|
|
}
|
|
|
|
// SlurmAPIError represents a structured error returned by the Slurm REST API.
|
|
// It captures both the HTTP details and the parsed Slurm error array when available.
|
|
type SlurmAPIError struct {
|
|
Response *http.Response
|
|
StatusCode int
|
|
Errors OpenapiErrors
|
|
Warnings OpenapiWarnings
|
|
Message string // raw body fallback when JSON parsing fails
|
|
}
|
|
|
|
func (e *SlurmAPIError) Error() string {
|
|
if len(e.Errors) > 0 {
|
|
first := e.Errors[0]
|
|
detail := ""
|
|
if first.Error != nil {
|
|
detail = *first.Error
|
|
} else if first.Description != nil {
|
|
detail = *first.Description
|
|
}
|
|
if detail != "" {
|
|
return fmt.Sprintf("%v %v: %d %s",
|
|
e.Response.Request.Method, e.Response.Request.URL,
|
|
e.StatusCode, detail)
|
|
}
|
|
}
|
|
return fmt.Sprintf("%v %v: %d %s",
|
|
e.Response.Request.Method, e.Response.Request.URL,
|
|
e.StatusCode, e.Message)
|
|
}
|
|
|
|
// IsNotFound reports whether err is a SlurmAPIError with HTTP 404 status.
|
|
func IsNotFound(err error) bool {
|
|
if apiErr, ok := err.(*SlurmAPIError); ok {
|
|
return apiErr.StatusCode == http.StatusNotFound
|
|
}
|
|
return false
|
|
}
|
|
|
|
// CheckResponse checks the API response for errors. It returns nil if the
|
|
// response is a 2xx status code. For non-2xx codes, it reads the response
|
|
// body, attempts to parse structured Slurm errors, and returns a SlurmAPIError.
|
|
func CheckResponse(r *http.Response) error {
|
|
if c := r.StatusCode; c >= 200 && c <= 299 {
|
|
return nil
|
|
}
|
|
|
|
data, err := io.ReadAll(r.Body)
|
|
if err != nil || len(data) == 0 {
|
|
return &SlurmAPIError{
|
|
Response: r,
|
|
StatusCode: r.StatusCode,
|
|
Message: r.Status,
|
|
}
|
|
}
|
|
|
|
apiErr := &SlurmAPIError{
|
|
Response: r,
|
|
StatusCode: r.StatusCode,
|
|
Message: string(data),
|
|
}
|
|
|
|
// Try to extract structured errors/warnings from JSON body.
|
|
var fields errorResponseFields
|
|
if json.Unmarshal(data, &fields) == nil {
|
|
apiErr.Errors = fields.Errors
|
|
apiErr.Warnings = fields.Warnings
|
|
}
|
|
|
|
return apiErr
|
|
}
|