Compare commits
10 Commits
52765f196a
...
962f63a5c6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
962f63a5c6 | ||
|
|
2b14e41d0d | ||
|
|
74230630c8 | ||
|
|
acd1e175bd | ||
|
|
f64e0dd8af | ||
|
|
4eba2525f5 | ||
|
|
0a3f9c1080 | ||
|
|
fe73d519c9 | ||
|
|
7af62eac41 | ||
|
|
874453d0c8 |
136
internal/slurm/slurmdb_accounts.go
Normal file
136
internal/slurm/slurmdb_accounts.go
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetAccountsOptions specifies optional parameters for GetAccounts and GetAccount.
|
||||||
|
type GetAccountsOptions struct {
|
||||||
|
Description *string `url:"description,omitempty"`
|
||||||
|
WithAssocs *string `url:"with_assocs,omitempty"`
|
||||||
|
WithCoords *string `url:"with_coords,omitempty"`
|
||||||
|
WithDeleted *string `url:"with_deleted,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAccounts lists all accounts.
|
||||||
|
func (s *SlurmdbAccountsService) GetAccounts(ctx context.Context, opts *GetAccountsOptions) (*OpenapiAccountsResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/accounts"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.Description != nil {
|
||||||
|
q.Set("description", *opts.Description)
|
||||||
|
}
|
||||||
|
if opts.WithAssocs != nil {
|
||||||
|
q.Set("with_assocs", *opts.WithAssocs)
|
||||||
|
}
|
||||||
|
if opts.WithCoords != nil {
|
||||||
|
q.Set("with_coords", *opts.WithCoords)
|
||||||
|
}
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAccountsResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAccount gets a single account by name.
|
||||||
|
func (s *SlurmdbAccountsService) GetAccount(ctx context.Context, accountName string, opts *GetAccountsOptions) (*OpenapiAccountsResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/account/%s", accountName)
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.WithAssocs != nil {
|
||||||
|
q.Set("with_assocs", *opts.WithAssocs)
|
||||||
|
}
|
||||||
|
if opts.WithCoords != nil {
|
||||||
|
q.Set("with_coords", *opts.WithCoords)
|
||||||
|
}
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAccountsResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostAccounts updates accounts.
|
||||||
|
func (s *SlurmdbAccountsService) PostAccounts(ctx context.Context, body *OpenapiAccountsResp) (*OpenapiAccountsResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/accounts"
|
||||||
|
req, err := s.client.NewRequest("POST", path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAccountsResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostAccountsAssociation adds accounts with conditional association.
|
||||||
|
func (s *SlurmdbAccountsService) PostAccountsAssociation(ctx context.Context, body *OpenapiAccountsAddCondResp) (*OpenapiAccountsAddCondRespStr, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/accounts_association"
|
||||||
|
req, err := s.client.NewRequest("POST", path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAccountsAddCondRespStr
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteAccount deletes an account by name.
|
||||||
|
func (s *SlurmdbAccountsService) DeleteAccount(ctx context.Context, accountName string) (*OpenapiAccountsRemovedResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/account/%s", accountName)
|
||||||
|
req, err := s.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAccountsRemovedResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
185
internal/slurm/slurmdb_accounts_test.go
Normal file
185
internal/slurm/slurmdb_accounts_test.go
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbAccountsService_GetAccounts(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/accounts", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"accounts": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbAccounts.GetAccounts(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Accounts) != 0 {
|
||||||
|
t.Errorf("expected empty accounts, got %d", len(resp.Accounts))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAccountsService_GetAccounts_WithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/accounts", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("with_deleted") != "true" {
|
||||||
|
t.Errorf("expected with_deleted=true, got %s", q.Get("with_deleted"))
|
||||||
|
}
|
||||||
|
if q.Get("with_assocs") != "true" {
|
||||||
|
t.Errorf("expected with_assocs=true, got %s", q.Get("with_assocs"))
|
||||||
|
}
|
||||||
|
if q.Get("with_coords") != "true" {
|
||||||
|
t.Errorf("expected with_coords=true, got %s", q.Get("with_coords"))
|
||||||
|
}
|
||||||
|
if q.Get("description") != "test" {
|
||||||
|
t.Errorf("expected description=test, got %s", q.Get("description"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"accounts": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetAccountsOptions{
|
||||||
|
Description: Ptr("test"),
|
||||||
|
WithDeleted: Ptr("true"),
|
||||||
|
WithAssocs: Ptr("true"),
|
||||||
|
WithCoords: Ptr("true"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbAccounts.GetAccounts(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAccountsService_GetAccount(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/account/testacct", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"accounts": [{"name": "testacct"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbAccounts.GetAccount(context.Background(), "testacct", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Accounts) != 1 {
|
||||||
|
t.Fatalf("expected 1 account, got %d", len(resp.Accounts))
|
||||||
|
}
|
||||||
|
if resp.Accounts[0].Name == nil || *resp.Accounts[0].Name != "testacct" {
|
||||||
|
t.Errorf("expected name=testacct, got %v", resp.Accounts[0].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAccountsService_PostAccounts(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/accounts", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
if ct := r.Header.Get("Content-Type"); ct != "application/json" {
|
||||||
|
t.Errorf("expected Content-Type application/json, got %s", ct)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"accounts": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
body := &OpenapiAccountsResp{}
|
||||||
|
resp, _, err := client.SlurmdbAccounts.PostAccounts(context.Background(), body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAccountsService_PostAccountsAssociation(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/accounts_association", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
if ct := r.Header.Get("Content-Type"); ct != "application/json" {
|
||||||
|
t.Errorf("expected Content-Type application/json, got %s", ct)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"added_accounts": "acct1,acct2"}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
body := &OpenapiAccountsAddCondResp{}
|
||||||
|
resp, _, err := client.SlurmdbAccounts.PostAccountsAssociation(context.Background(), body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if resp.AddedAccounts == nil || *resp.AddedAccounts != "acct1,acct2" {
|
||||||
|
t.Errorf("expected added_accounts=acct1,acct2, got %v", resp.AddedAccounts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAccountsService_DeleteAccount(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/account/testacct", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
fmt.Fprint(w, `{"removed_accounts": ["testacct"]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbAccounts.DeleteAccount(context.Background(), "testacct")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.RemovedAccounts) != 1 || resp.RemovedAccounts[0] != "testacct" {
|
||||||
|
t.Errorf("expected removed_accounts=[testacct], got %v", resp.RemovedAccounts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAccountsService_GetAccount_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/account/nonexistent", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "account not found"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbAccounts.GetAccount(context.Background(), "nonexistent", nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 404 response")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "404") {
|
||||||
|
t.Errorf("expected error to contain 404, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
208
internal/slurm/slurmdb_assocs.go
Normal file
208
internal/slurm/slurmdb_assocs.go
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetAssocsOptions specifies optional query parameters for association endpoints.
|
||||||
|
// Shared by GetAssociations, GetAssociation, DeleteAssociations, and DeleteAssociation.
|
||||||
|
type GetAssocsOptions struct {
|
||||||
|
Account *string `url:"account,omitempty"`
|
||||||
|
Cluster *string `url:"cluster,omitempty"`
|
||||||
|
DefaultQos *string `url:"default_qos,omitempty"`
|
||||||
|
Format *string `url:"format,omitempty"`
|
||||||
|
ID *string `url:"id,omitempty"`
|
||||||
|
OnlyDefaults *string `url:"only_defaults,omitempty"`
|
||||||
|
ParentAccount *string `url:"parent_account,omitempty"`
|
||||||
|
Partition *string `url:"partition,omitempty"`
|
||||||
|
Qos *string `url:"qos,omitempty"`
|
||||||
|
UsageEnd *string `url:"usage_end,omitempty"`
|
||||||
|
UsageStart *string `url:"usage_start,omitempty"`
|
||||||
|
User *string `url:"user,omitempty"`
|
||||||
|
WithUsage *string `url:"with_usage,omitempty"`
|
||||||
|
WithDeleted *string `url:"with_deleted,omitempty"`
|
||||||
|
WithRawQos *string `url:"with_raw_qos,omitempty"`
|
||||||
|
WithSubAccts *string `url:"with_sub_accts,omitempty"`
|
||||||
|
WithoutParentInfo *string `url:"without_parent_info,omitempty"`
|
||||||
|
WithoutParentLimits *string `url:"without_parent_limits,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// setAssocsQueryParams applies GetAssocsOptions fields as query parameters on the request URL.
|
||||||
|
func setAssocsQueryParams(reqURL *url.URL, opts *GetAssocsOptions) {
|
||||||
|
if opts == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
q := reqURL.Query()
|
||||||
|
if opts.Account != nil {
|
||||||
|
q.Set("account", *opts.Account)
|
||||||
|
}
|
||||||
|
if opts.Cluster != nil {
|
||||||
|
q.Set("cluster", *opts.Cluster)
|
||||||
|
}
|
||||||
|
if opts.DefaultQos != nil {
|
||||||
|
q.Set("default_qos", *opts.DefaultQos)
|
||||||
|
}
|
||||||
|
if opts.Format != nil {
|
||||||
|
q.Set("format", *opts.Format)
|
||||||
|
}
|
||||||
|
if opts.ID != nil {
|
||||||
|
q.Set("id", *opts.ID)
|
||||||
|
}
|
||||||
|
if opts.OnlyDefaults != nil {
|
||||||
|
q.Set("only_defaults", *opts.OnlyDefaults)
|
||||||
|
}
|
||||||
|
if opts.ParentAccount != nil {
|
||||||
|
q.Set("parent_account", *opts.ParentAccount)
|
||||||
|
}
|
||||||
|
if opts.Partition != nil {
|
||||||
|
q.Set("partition", *opts.Partition)
|
||||||
|
}
|
||||||
|
if opts.Qos != nil {
|
||||||
|
q.Set("qos", *opts.Qos)
|
||||||
|
}
|
||||||
|
if opts.UsageEnd != nil {
|
||||||
|
q.Set("usage_end", *opts.UsageEnd)
|
||||||
|
}
|
||||||
|
if opts.UsageStart != nil {
|
||||||
|
q.Set("usage_start", *opts.UsageStart)
|
||||||
|
}
|
||||||
|
if opts.User != nil {
|
||||||
|
q.Set("user", *opts.User)
|
||||||
|
}
|
||||||
|
if opts.WithUsage != nil {
|
||||||
|
q.Set("with_usage", *opts.WithUsage)
|
||||||
|
}
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
if opts.WithRawQos != nil {
|
||||||
|
q.Set("with_raw_qos", *opts.WithRawQos)
|
||||||
|
}
|
||||||
|
if opts.WithSubAccts != nil {
|
||||||
|
q.Set("with_sub_accts", *opts.WithSubAccts)
|
||||||
|
}
|
||||||
|
if opts.WithoutParentInfo != nil {
|
||||||
|
q.Set("without_parent_info", *opts.WithoutParentInfo)
|
||||||
|
}
|
||||||
|
if opts.WithoutParentLimits != nil {
|
||||||
|
q.Set("without_parent_limits", *opts.WithoutParentLimits)
|
||||||
|
}
|
||||||
|
reqURL.RawQuery = q.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAssociations lists all associations matching the given options.
|
||||||
|
func (s *SlurmdbAssocsService) GetAssociations(ctx context.Context, opts *GetAssocsOptions) (*OpenapiAssocsResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/associations"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
setAssocsQueryParams(u, opts)
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAssocsResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAssociation gets a single association matching the given options.
|
||||||
|
func (s *SlurmdbAssocsService) GetAssociation(ctx context.Context, opts *GetAssocsOptions) (*OpenapiAssocsResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/association"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
setAssocsQueryParams(u, opts)
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAssocsResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostAssociations creates or updates associations.
|
||||||
|
func (s *SlurmdbAssocsService) PostAssociations(ctx context.Context, body *OpenapiAssocsResp) (*OpenapiResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/associations"
|
||||||
|
req, err := s.client.NewRequest("POST", path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteAssociations deletes associations matching the given options.
|
||||||
|
func (s *SlurmdbAssocsService) DeleteAssociations(ctx context.Context, opts *GetAssocsOptions) (*OpenapiAssocsRemovedResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/associations"
|
||||||
|
req, err := s.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
setAssocsQueryParams(u, opts)
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAssocsRemovedResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteAssociation deletes a single association matching the given options.
|
||||||
|
func (s *SlurmdbAssocsService) DeleteAssociation(ctx context.Context, opts *GetAssocsOptions) (*OpenapiAssocsRemovedResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/association"
|
||||||
|
req, err := s.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
setAssocsQueryParams(u, opts)
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiAssocsRemovedResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
352
internal/slurm/slurmdb_assocs_test.go
Normal file
352
internal/slurm/slurmdb_assocs_test.go
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_GetAssociations(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/associations", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"associations": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbAssocs.GetAssociations(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_GetAssociations_WithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/associations", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("account") != "testacct" {
|
||||||
|
t.Errorf("expected account=testacct, got %s", q.Get("account"))
|
||||||
|
}
|
||||||
|
if q.Get("cluster") != "testcluster" {
|
||||||
|
t.Errorf("expected cluster=testcluster, got %s", q.Get("cluster"))
|
||||||
|
}
|
||||||
|
if q.Get("user") != "testuser" {
|
||||||
|
t.Errorf("expected user=testuser, got %s", q.Get("user"))
|
||||||
|
}
|
||||||
|
if q.Get("with_deleted") != "true" {
|
||||||
|
t.Errorf("expected with_deleted=true, got %s", q.Get("with_deleted"))
|
||||||
|
}
|
||||||
|
if q.Get("with_usage") != "true" {
|
||||||
|
t.Errorf("expected with_usage=true, got %s", q.Get("with_usage"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"associations": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetAssocsOptions{
|
||||||
|
Account: Ptr("testacct"),
|
||||||
|
Cluster: Ptr("testcluster"),
|
||||||
|
User: Ptr("testuser"),
|
||||||
|
WithDeleted: Ptr("true"),
|
||||||
|
WithUsage: Ptr("true"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbAssocs.GetAssociations(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_GetAssociation(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/association", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"associations": [{"account": "testacct"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetAssocsOptions{
|
||||||
|
Account: Ptr("testacct"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbAssocs.GetAssociation(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_GetAssociation_AllQueryParams(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/association", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
expectedParams := []string{
|
||||||
|
"account", "cluster", "default_qos", "format", "id",
|
||||||
|
"only_defaults", "parent_account", "partition", "qos",
|
||||||
|
"usage_end", "usage_start", "user", "with_usage",
|
||||||
|
"with_deleted", "with_raw_qos", "with_sub_accts",
|
||||||
|
"without_parent_info", "without_parent_limits",
|
||||||
|
}
|
||||||
|
for _, p := range expectedParams {
|
||||||
|
if q.Get(p) == "" {
|
||||||
|
t.Errorf("expected query param %s to be set", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"associations": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetAssocsOptions{
|
||||||
|
Account: Ptr("acct"),
|
||||||
|
Cluster: Ptr("clust"),
|
||||||
|
DefaultQos: Ptr("dqos"),
|
||||||
|
Format: Ptr("fmt"),
|
||||||
|
ID: Ptr("1"),
|
||||||
|
OnlyDefaults: Ptr("1"),
|
||||||
|
ParentAccount: Ptr("parent"),
|
||||||
|
Partition: Ptr("part"),
|
||||||
|
Qos: Ptr("qos"),
|
||||||
|
UsageEnd: Ptr("9999"),
|
||||||
|
UsageStart: Ptr("0000"),
|
||||||
|
User: Ptr("usr"),
|
||||||
|
WithUsage: Ptr("1"),
|
||||||
|
WithDeleted: Ptr("1"),
|
||||||
|
WithRawQos: Ptr("1"),
|
||||||
|
WithSubAccts: Ptr("1"),
|
||||||
|
WithoutParentInfo: Ptr("1"),
|
||||||
|
WithoutParentLimits: Ptr("1"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbAssocs.GetAssociation(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_PostAssociations(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/associations", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
if ct := r.Header.Get("Content-Type"); ct != "application/json" {
|
||||||
|
t.Errorf("expected Content-Type application/json, got %s", ct)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"meta": {"plugin": {"type": "openapi/v0.0.40"}}}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
body := &OpenapiAssocsResp{
|
||||||
|
Associations: AssocList{},
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbAssocs.PostAssociations(context.Background(), body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_DeleteAssociations(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/associations", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("account") != "delacct" {
|
||||||
|
t.Errorf("expected account=delacct, got %s", q.Get("account"))
|
||||||
|
}
|
||||||
|
if q.Get("cluster") != "delcluster" {
|
||||||
|
t.Errorf("expected cluster=delcluster, got %s", q.Get("cluster"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"removed_associations": ["acct1"]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetAssocsOptions{
|
||||||
|
Account: Ptr("delacct"),
|
||||||
|
Cluster: Ptr("delcluster"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbAssocs.DeleteAssociations(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_DeleteAssociation(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/association", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("user") != "deluser" {
|
||||||
|
t.Errorf("expected user=deluser, got %s", q.Get("user"))
|
||||||
|
}
|
||||||
|
if q.Get("partition") != "delpart" {
|
||||||
|
t.Errorf("expected partition=delpart, got %s", q.Get("partition"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"removed_associations": ["assoc1"]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetAssocsOptions{
|
||||||
|
User: Ptr("deluser"),
|
||||||
|
Partition: Ptr("delpart"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbAssocs.DeleteAssociation(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_DeleteAssociation_NoOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/association", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if len(q) != 0 {
|
||||||
|
t.Errorf("expected no query params, got %v", q)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"removed_associations": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbAssocs.DeleteAssociation(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_GetAssociations_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/associations", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbAssocs.GetAssociations(context.Background(), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 500 response")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "500") {
|
||||||
|
t.Errorf("expected error to contain 500, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_DeleteAssociations_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/associations", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "not found"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbAssocs.DeleteAssociations(context.Background(), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 404 response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbAssocsService_PathCorrectness(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/associations", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == "GET" {
|
||||||
|
fmt.Fprint(w, `{"associations": [], "path": "plural"}`)
|
||||||
|
} else if r.Method == "DELETE" {
|
||||||
|
fmt.Fprint(w, `{"removed_associations": [], "path": "plural"}`)
|
||||||
|
} else {
|
||||||
|
fmt.Fprint(w, `{"meta": {}}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/association", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == "GET" {
|
||||||
|
fmt.Fprint(w, `{"associations": [], "path": "singular"}`)
|
||||||
|
} else if r.Method == "DELETE" {
|
||||||
|
fmt.Fprint(w, `{"removed_associations": [], "path": "singular"}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
|
||||||
|
resp, _, err := client.SlurmdbAssocs.GetAssociations(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetAssociations: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("GetAssociations: expected non-nil response")
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _, err = client.SlurmdbAssocs.GetAssociation(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetAssociation: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("GetAssociation: expected non-nil response")
|
||||||
|
}
|
||||||
|
|
||||||
|
delResp, _, err := client.SlurmdbAssocs.DeleteAssociations(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("DeleteAssociations: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if delResp == nil {
|
||||||
|
t.Fatal("DeleteAssociations: expected non-nil response")
|
||||||
|
}
|
||||||
|
|
||||||
|
delResp, _, err = client.SlurmdbAssocs.DeleteAssociation(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("DeleteAssociation: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if delResp == nil {
|
||||||
|
t.Fatal("DeleteAssociation: expected non-nil response")
|
||||||
|
}
|
||||||
|
|
||||||
|
postResp, _, err := client.SlurmdbAssocs.PostAssociations(context.Background(), &OpenapiAssocsResp{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("PostAssociations: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if postResp == nil {
|
||||||
|
t.Fatal("PostAssociations: expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
221
internal/slurm/slurmdb_clusters.go
Normal file
221
internal/slurm/slurmdb_clusters.go
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cluster classification constants for GetClustersOptions.Classification
|
||||||
|
// and DeleteClusterOptions.Classification.
|
||||||
|
const (
|
||||||
|
ClusterClassificationUNCLASSIFIED = "UNCLASSIFIED"
|
||||||
|
ClusterClassificationCapability = "CAPABILITY"
|
||||||
|
ClusterClassificationCapacity = "CAPACITY"
|
||||||
|
ClusterClassificationCapapacity = "CAPAPACITY"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cluster flags constants for GetClustersOptions.Flags
|
||||||
|
// and DeleteClusterOptions.Flags.
|
||||||
|
const (
|
||||||
|
ClusterFlagRegistering = "REGISTERING"
|
||||||
|
ClusterFlagMultipleSlurmd = "MULTIPLE_SLURMD"
|
||||||
|
ClusterFlagFrontEnd = "FRONT_END"
|
||||||
|
ClusterFlagCrayNative = "CRAY_NATIVE"
|
||||||
|
ClusterFlagFederation = "FEDERATION"
|
||||||
|
ClusterFlagExternal = "EXTERNAL"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetClustersOptions specifies optional query parameters for GetClusters and GetCluster.
|
||||||
|
type GetClustersOptions struct {
|
||||||
|
Classification *string `url:"classification,omitempty"`
|
||||||
|
Cluster *string `url:"cluster,omitempty"` // CSV cluster list
|
||||||
|
Federation *string `url:"federation,omitempty"` // CSV federation list
|
||||||
|
Flags *string `url:"flags,omitempty"` // Use ClusterFlag* constants
|
||||||
|
Format *string `url:"format,omitempty"` // CSV format list
|
||||||
|
RpcVersion *string `url:"rpc_version,omitempty"` // CSV RPC version list
|
||||||
|
UsageEnd *string `url:"usage_end,omitempty"` // Usage end UNIX timestamp (seconds)
|
||||||
|
UsageStart *string `url:"usage_start,omitempty"` // Usage start UNIX timestamp (seconds)
|
||||||
|
WithDeleted *string `url:"with_deleted,omitempty"` // Include deleted clusters
|
||||||
|
WithUsage *string `url:"with_usage,omitempty"` // Query usage
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteClusterOptions specifies optional query parameters for DeleteCluster.
|
||||||
|
type DeleteClusterOptions struct {
|
||||||
|
Classification *string `url:"classification,omitempty"`
|
||||||
|
Cluster *string `url:"cluster,omitempty"`
|
||||||
|
Federation *string `url:"federation,omitempty"`
|
||||||
|
Flags *string `url:"flags,omitempty"`
|
||||||
|
Format *string `url:"format,omitempty"`
|
||||||
|
RpcVersion *string `url:"rpc_version,omitempty"`
|
||||||
|
UsageEnd *string `url:"usage_end,omitempty"`
|
||||||
|
UsageStart *string `url:"usage_start,omitempty"`
|
||||||
|
WithDeleted *string `url:"with_deleted,omitempty"`
|
||||||
|
WithUsage *string `url:"with_usage,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func addGetClustersQueryParams(req *http.Request, opts *GetClustersOptions) error {
|
||||||
|
if opts == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
u, err := url.Parse(req.URL.String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.Classification != nil {
|
||||||
|
q.Set("classification", *opts.Classification)
|
||||||
|
}
|
||||||
|
if opts.Cluster != nil {
|
||||||
|
q.Set("cluster", *opts.Cluster)
|
||||||
|
}
|
||||||
|
if opts.Federation != nil {
|
||||||
|
q.Set("federation", *opts.Federation)
|
||||||
|
}
|
||||||
|
if opts.Flags != nil {
|
||||||
|
q.Set("flags", *opts.Flags)
|
||||||
|
}
|
||||||
|
if opts.Format != nil {
|
||||||
|
q.Set("format", *opts.Format)
|
||||||
|
}
|
||||||
|
if opts.RpcVersion != nil {
|
||||||
|
q.Set("rpc_version", *opts.RpcVersion)
|
||||||
|
}
|
||||||
|
if opts.UsageEnd != nil {
|
||||||
|
q.Set("usage_end", *opts.UsageEnd)
|
||||||
|
}
|
||||||
|
if opts.UsageStart != nil {
|
||||||
|
q.Set("usage_start", *opts.UsageStart)
|
||||||
|
}
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
if opts.WithUsage != nil {
|
||||||
|
q.Set("with_usage", *opts.WithUsage)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// addDeleteClusterQueryParams applies DeleteClusterOptions query params to the request URL.
|
||||||
|
func addDeleteClusterQueryParams(req *http.Request, opts *DeleteClusterOptions) error {
|
||||||
|
if opts == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
u, err := url.Parse(req.URL.String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.Classification != nil {
|
||||||
|
q.Set("classification", *opts.Classification)
|
||||||
|
}
|
||||||
|
if opts.Cluster != nil {
|
||||||
|
q.Set("cluster", *opts.Cluster)
|
||||||
|
}
|
||||||
|
if opts.Federation != nil {
|
||||||
|
q.Set("federation", *opts.Federation)
|
||||||
|
}
|
||||||
|
if opts.Flags != nil {
|
||||||
|
q.Set("flags", *opts.Flags)
|
||||||
|
}
|
||||||
|
if opts.Format != nil {
|
||||||
|
q.Set("format", *opts.Format)
|
||||||
|
}
|
||||||
|
if opts.RpcVersion != nil {
|
||||||
|
q.Set("rpc_version", *opts.RpcVersion)
|
||||||
|
}
|
||||||
|
if opts.UsageEnd != nil {
|
||||||
|
q.Set("usage_end", *opts.UsageEnd)
|
||||||
|
}
|
||||||
|
if opts.UsageStart != nil {
|
||||||
|
q.Set("usage_start", *opts.UsageStart)
|
||||||
|
}
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
if opts.WithUsage != nil {
|
||||||
|
q.Set("with_usage", *opts.WithUsage)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetClusters lists all clusters.
|
||||||
|
func (s *SlurmdbClustersService) GetClusters(ctx context.Context, opts *GetClustersOptions) (*OpenapiClustersResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/clusters"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := addGetClustersQueryParams(req, opts); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiClustersResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCluster gets a single cluster by name.
|
||||||
|
func (s *SlurmdbClustersService) GetCluster(ctx context.Context, clusterName string, opts *GetClustersOptions) (*OpenapiClustersResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/cluster/%s", clusterName)
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := addGetClustersQueryParams(req, opts); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiClustersResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostClusters creates or updates clusters.
|
||||||
|
func (s *SlurmdbClustersService) PostClusters(ctx context.Context, body *OpenapiClustersResp) (*OpenapiResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/clusters"
|
||||||
|
req, err := s.client.NewRequest("POST", path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteCluster deletes a cluster by name.
|
||||||
|
func (s *SlurmdbClustersService) DeleteCluster(ctx context.Context, clusterName string, opts *DeleteClusterOptions) (*OpenapiClustersRemovedResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/cluster/%s", clusterName)
|
||||||
|
req, err := s.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := addDeleteClusterQueryParams(req, opts); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiClustersRemovedResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
221
internal/slurm/slurmdb_clusters_test.go
Normal file
221
internal/slurm/slurmdb_clusters_test.go
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbClustersService_GetClusters(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/clusters", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"clusters": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbClusters.GetClusters(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbClustersService_GetClusters_WithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/clusters", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("classification") != ClusterClassificationCapability {
|
||||||
|
t.Errorf("expected classification=%s, got %s", ClusterClassificationCapability, q.Get("classification"))
|
||||||
|
}
|
||||||
|
if q.Get("flags") != ClusterFlagFederation {
|
||||||
|
t.Errorf("expected flags=%s, got %s", ClusterFlagFederation, q.Get("flags"))
|
||||||
|
}
|
||||||
|
if q.Get("with_deleted") != "true" {
|
||||||
|
t.Errorf("expected with_deleted=true, got %s", q.Get("with_deleted"))
|
||||||
|
}
|
||||||
|
if q.Get("with_usage") != "true" {
|
||||||
|
t.Errorf("expected with_usage=true, got %s", q.Get("with_usage"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"clusters": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetClustersOptions{
|
||||||
|
Classification: Ptr(ClusterClassificationCapability),
|
||||||
|
Flags: Ptr(ClusterFlagFederation),
|
||||||
|
WithDeleted: Ptr("true"),
|
||||||
|
WithUsage: Ptr("true"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbClusters.GetClusters(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbClustersService_GetCluster(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/cluster/test-cluster", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"clusters": [{"name": "test-cluster"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbClusters.GetCluster(context.Background(), "test-cluster", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Clusters) != 1 {
|
||||||
|
t.Fatalf("expected 1 cluster, got %d", len(resp.Clusters))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbClustersService_GetCluster_WithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/cluster/mycluster", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("classification") != ClusterClassificationCapacity {
|
||||||
|
t.Errorf("expected classification=%s, got %s", ClusterClassificationCapacity, q.Get("classification"))
|
||||||
|
}
|
||||||
|
if q.Get("usage_start") != "1000000" {
|
||||||
|
t.Errorf("expected usage_start=1000000, got %s", q.Get("usage_start"))
|
||||||
|
}
|
||||||
|
if q.Get("usage_end") != "2000000" {
|
||||||
|
t.Errorf("expected usage_end=2000000, got %s", q.Get("usage_end"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"clusters": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetClustersOptions{
|
||||||
|
Classification: Ptr(ClusterClassificationCapacity),
|
||||||
|
UsageStart: Ptr("1000000"),
|
||||||
|
UsageEnd: Ptr("2000000"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbClusters.GetCluster(context.Background(), "mycluster", opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbClustersService_PostClusters(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/clusters", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
if ct := r.Header.Get("Content-Type"); ct != "application/json" {
|
||||||
|
t.Errorf("expected Content-Type application/json, got %s", ct)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
body := &OpenapiClustersResp{}
|
||||||
|
resp, _, err := client.SlurmdbClusters.PostClusters(context.Background(), body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbClustersService_DeleteCluster(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/cluster/old-cluster", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("classification") != ClusterClassificationUNCLASSIFIED {
|
||||||
|
t.Errorf("expected classification=%s, got %s", ClusterClassificationUNCLASSIFIED, q.Get("classification"))
|
||||||
|
}
|
||||||
|
if q.Get("with_deleted") != "true" {
|
||||||
|
t.Errorf("expected with_deleted=true, got %s", q.Get("with_deleted"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"deleted_clusters": ["old-cluster"]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &DeleteClusterOptions{
|
||||||
|
Classification: Ptr(ClusterClassificationUNCLASSIFIED),
|
||||||
|
WithDeleted: Ptr("true"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbClusters.DeleteCluster(context.Background(), "old-cluster", opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.DeletedClusters) != 1 {
|
||||||
|
t.Fatalf("expected 1 deleted cluster, got %d", len(resp.DeletedClusters))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbClustersService_DeleteCluster_NoOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/cluster/test-cluster", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if len(q) != 0 {
|
||||||
|
t.Errorf("expected no query params, got %v", q)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"deleted_clusters": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbClusters.DeleteCluster(context.Background(), "test-cluster", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbClustersService_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/clusters", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbClusters.GetClusters(context.Background(), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 500 response")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "500") {
|
||||||
|
t.Errorf("expected error to contain 500, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
33
internal/slurm/slurmdb_config.go
Normal file
33
internal/slurm/slurmdb_config.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
// GetConfig returns slurmdbd configuration.
|
||||||
|
func (s *SlurmdbConfigService) GetConfig(ctx context.Context) (*OpenapiSlurmdbdConfigResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/config"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
var result OpenapiSlurmdbdConfigResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostConfig updates slurmdbd configuration.
|
||||||
|
func (s *SlurmdbConfigService) PostConfig(ctx context.Context, config *OpenapiSlurmdbdConfigResp) (*OpenapiResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/config"
|
||||||
|
req, err := s.client.NewRequest("POST", path, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
var result OpenapiResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
68
internal/slurm/slurmdb_config_test.go
Normal file
68
internal/slurm/slurmdb_config_test.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbConfigService_GetConfig(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/config", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"accounts": [], "clusters": [], "qos": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbConfig.GetConfig(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbConfigService_PostConfig(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/config", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
fmt.Fprint(w, `{}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
config := &OpenapiSlurmdbdConfigResp{}
|
||||||
|
resp, _, err := client.SlurmdbConfig.PostConfig(context.Background(), config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbConfigService_GetConfig_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/config", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbConfig.GetConfig(context.Background())
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 500 response")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "500") {
|
||||||
|
t.Errorf("expected error to contain 500, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
90
internal/slurm/slurmdb_instances.go
Normal file
90
internal/slurm/slurmdb_instances.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetInstancesOptions specifies optional parameters for GetInstances and GetInstance.
|
||||||
|
type GetInstancesOptions struct {
|
||||||
|
Cluster *string `url:"cluster,omitempty"`
|
||||||
|
Extra *string `url:"extra,omitempty"`
|
||||||
|
InstanceID *string `url:"instance_id,omitempty"`
|
||||||
|
InstanceType *string `url:"instance_type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInstances lists all instances.
|
||||||
|
func (s *SlurmdbInstancesService) GetInstances(ctx context.Context, opts *GetInstancesOptions) (*OpenapiInstancesResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/instances"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.Cluster != nil {
|
||||||
|
q.Set("cluster", *opts.Cluster)
|
||||||
|
}
|
||||||
|
if opts.Extra != nil {
|
||||||
|
q.Set("extra", *opts.Extra)
|
||||||
|
}
|
||||||
|
if opts.InstanceID != nil {
|
||||||
|
q.Set("instance_id", *opts.InstanceID)
|
||||||
|
}
|
||||||
|
if opts.InstanceType != nil {
|
||||||
|
q.Set("instance_type", *opts.InstanceType)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiInstancesResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInstance returns a single instance matching the query parameters.
|
||||||
|
func (s *SlurmdbInstancesService) GetInstance(ctx context.Context, opts *GetInstancesOptions) (*OpenapiInstancesResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/instance"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.Cluster != nil {
|
||||||
|
q.Set("cluster", *opts.Cluster)
|
||||||
|
}
|
||||||
|
if opts.Extra != nil {
|
||||||
|
q.Set("extra", *opts.Extra)
|
||||||
|
}
|
||||||
|
if opts.InstanceID != nil {
|
||||||
|
q.Set("instance_id", *opts.InstanceID)
|
||||||
|
}
|
||||||
|
if opts.InstanceType != nil {
|
||||||
|
q.Set("instance_type", *opts.InstanceType)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiInstancesResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
93
internal/slurm/slurmdb_instances_test.go
Normal file
93
internal/slurm/slurmdb_instances_test.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbInstancesService_GetInstances(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/instances", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"instances": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbInstances.GetInstances(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbInstancesService_GetInstancesWithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/instances", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("cluster") != "test-cluster" {
|
||||||
|
t.Errorf("expected cluster=test-cluster, got %s", q.Get("cluster"))
|
||||||
|
}
|
||||||
|
if q.Get("extra") != "some-extra" {
|
||||||
|
t.Errorf("expected extra=some-extra, got %s", q.Get("extra"))
|
||||||
|
}
|
||||||
|
if q.Get("instance_id") != "i-12345" {
|
||||||
|
t.Errorf("expected instance_id=i-12345, got %s", q.Get("instance_id"))
|
||||||
|
}
|
||||||
|
if q.Get("instance_type") != "t2.micro" {
|
||||||
|
t.Errorf("expected instance_type=t2.micro, got %s", q.Get("instance_type"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"instances": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetInstancesOptions{
|
||||||
|
Cluster: Ptr("test-cluster"),
|
||||||
|
Extra: Ptr("some-extra"),
|
||||||
|
InstanceID: Ptr("i-12345"),
|
||||||
|
InstanceType: Ptr("t2.micro"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbInstances.GetInstances(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbInstancesService_GetInstance(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/instance", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"instances": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbInstances.GetInstance(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbInstancesService_GetInstances_InvalidURL(t *testing.T) {
|
||||||
|
client, _ := NewClient("http://invalid-host-does-not-exist.local", nil)
|
||||||
|
_, _, err := client.SlurmdbInstances.GetInstances(context.Background(), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for invalid URL")
|
||||||
|
}
|
||||||
|
}
|
||||||
218
internal/slurm/slurmdb_jobs.go
Normal file
218
internal/slurm/slurmdb_jobs.go
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetSlurmdbJobsOptions specifies optional query parameters for SlurmdbJobsService.GetJobs.
|
||||||
|
// All 41 parameters correspond to the GET /slurmdb/v0.0.40/jobs endpoint.
|
||||||
|
type GetSlurmdbJobsOptions struct {
|
||||||
|
Account *string `url:"account,omitempty"`
|
||||||
|
Association *string `url:"association,omitempty"`
|
||||||
|
Cluster *string `url:"cluster,omitempty"`
|
||||||
|
Constraints *string `url:"constraints,omitempty"`
|
||||||
|
CpusMax *string `url:"cpus_max,omitempty"`
|
||||||
|
CpusMin *string `url:"cpus_min,omitempty"`
|
||||||
|
SchedulerUnset *string `url:"scheduler_unset,omitempty"`
|
||||||
|
ScheduledOnSubmit *string `url:"scheduled_on_submit,omitempty"`
|
||||||
|
ScheduledByMain *string `url:"scheduled_by_main,omitempty"`
|
||||||
|
ScheduledByBackfill *string `url:"scheduled_by_backfill,omitempty"`
|
||||||
|
JobStarted *string `url:"job_started,omitempty"`
|
||||||
|
ExitCode *string `url:"exit_code,omitempty"`
|
||||||
|
ShowDuplicates *string `url:"show_duplicates,omitempty"`
|
||||||
|
SkipSteps *string `url:"skip_steps,omitempty"`
|
||||||
|
DisableTruncateUsageTime *string `url:"disable_truncate_usage_time,omitempty"`
|
||||||
|
WholeHetjob *string `url:"whole_hetjob,omitempty"`
|
||||||
|
DisableWholeHetjob *string `url:"disable_whole_hetjob,omitempty"`
|
||||||
|
DisableWaitForResult *string `url:"disable_wait_for_result,omitempty"`
|
||||||
|
UsageTimeAsSubmitTime *string `url:"usage_time_as_submit_time,omitempty"`
|
||||||
|
ShowBatchScript *string `url:"show_batch_script,omitempty"`
|
||||||
|
ShowJobEnvironment *string `url:"show_job_environment,omitempty"`
|
||||||
|
Format *string `url:"format,omitempty"`
|
||||||
|
Groups *string `url:"groups,omitempty"`
|
||||||
|
JobName *string `url:"job_name,omitempty"`
|
||||||
|
NodesMax *string `url:"nodes_max,omitempty"`
|
||||||
|
NodesMin *string `url:"nodes_min,omitempty"`
|
||||||
|
Partition *string `url:"partition,omitempty"`
|
||||||
|
Qos *string `url:"qos,omitempty"`
|
||||||
|
Reason *string `url:"reason,omitempty"`
|
||||||
|
Reservation *string `url:"reservation,omitempty"`
|
||||||
|
ReservationID *string `url:"reservation_id,omitempty"`
|
||||||
|
State *string `url:"state,omitempty"`
|
||||||
|
Step *string `url:"step,omitempty"`
|
||||||
|
TimelimitMax *string `url:"timelimit_max,omitempty"`
|
||||||
|
TimelimitMin *string `url:"timelimit_min,omitempty"`
|
||||||
|
EndTime *string `url:"end_time,omitempty"`
|
||||||
|
StartTime *string `url:"start_time,omitempty"`
|
||||||
|
SubmitTime *string `url:"submit_time,omitempty"`
|
||||||
|
Node *string `url:"node,omitempty"`
|
||||||
|
Users *string `url:"users,omitempty"`
|
||||||
|
Wckey *string `url:"wckey,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetJobs queries the SlurmDBD for jobs matching the given options.
|
||||||
|
func (s *SlurmdbJobsService) GetJobs(ctx context.Context, opts *GetSlurmdbJobsOptions) (*OpenapiSlurmdbdJobsResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/jobs"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.Account != nil {
|
||||||
|
q.Set("account", *opts.Account)
|
||||||
|
}
|
||||||
|
if opts.Association != nil {
|
||||||
|
q.Set("association", *opts.Association)
|
||||||
|
}
|
||||||
|
if opts.Cluster != nil {
|
||||||
|
q.Set("cluster", *opts.Cluster)
|
||||||
|
}
|
||||||
|
if opts.Constraints != nil {
|
||||||
|
q.Set("constraints", *opts.Constraints)
|
||||||
|
}
|
||||||
|
if opts.CpusMax != nil {
|
||||||
|
q.Set("cpus_max", *opts.CpusMax)
|
||||||
|
}
|
||||||
|
if opts.CpusMin != nil {
|
||||||
|
q.Set("cpus_min", *opts.CpusMin)
|
||||||
|
}
|
||||||
|
if opts.SchedulerUnset != nil {
|
||||||
|
q.Set("scheduler_unset", *opts.SchedulerUnset)
|
||||||
|
}
|
||||||
|
if opts.ScheduledOnSubmit != nil {
|
||||||
|
q.Set("scheduled_on_submit", *opts.ScheduledOnSubmit)
|
||||||
|
}
|
||||||
|
if opts.ScheduledByMain != nil {
|
||||||
|
q.Set("scheduled_by_main", *opts.ScheduledByMain)
|
||||||
|
}
|
||||||
|
if opts.ScheduledByBackfill != nil {
|
||||||
|
q.Set("scheduled_by_backfill", *opts.ScheduledByBackfill)
|
||||||
|
}
|
||||||
|
if opts.JobStarted != nil {
|
||||||
|
q.Set("job_started", *opts.JobStarted)
|
||||||
|
}
|
||||||
|
if opts.ExitCode != nil {
|
||||||
|
q.Set("exit_code", *opts.ExitCode)
|
||||||
|
}
|
||||||
|
if opts.ShowDuplicates != nil {
|
||||||
|
q.Set("show_duplicates", *opts.ShowDuplicates)
|
||||||
|
}
|
||||||
|
if opts.SkipSteps != nil {
|
||||||
|
q.Set("skip_steps", *opts.SkipSteps)
|
||||||
|
}
|
||||||
|
if opts.DisableTruncateUsageTime != nil {
|
||||||
|
q.Set("disable_truncate_usage_time", *opts.DisableTruncateUsageTime)
|
||||||
|
}
|
||||||
|
if opts.WholeHetjob != nil {
|
||||||
|
q.Set("whole_hetjob", *opts.WholeHetjob)
|
||||||
|
}
|
||||||
|
if opts.DisableWholeHetjob != nil {
|
||||||
|
q.Set("disable_whole_hetjob", *opts.DisableWholeHetjob)
|
||||||
|
}
|
||||||
|
if opts.DisableWaitForResult != nil {
|
||||||
|
q.Set("disable_wait_for_result", *opts.DisableWaitForResult)
|
||||||
|
}
|
||||||
|
if opts.UsageTimeAsSubmitTime != nil {
|
||||||
|
q.Set("usage_time_as_submit_time", *opts.UsageTimeAsSubmitTime)
|
||||||
|
}
|
||||||
|
if opts.ShowBatchScript != nil {
|
||||||
|
q.Set("show_batch_script", *opts.ShowBatchScript)
|
||||||
|
}
|
||||||
|
if opts.ShowJobEnvironment != nil {
|
||||||
|
q.Set("show_job_environment", *opts.ShowJobEnvironment)
|
||||||
|
}
|
||||||
|
if opts.Format != nil {
|
||||||
|
q.Set("format", *opts.Format)
|
||||||
|
}
|
||||||
|
if opts.Groups != nil {
|
||||||
|
q.Set("groups", *opts.Groups)
|
||||||
|
}
|
||||||
|
if opts.JobName != nil {
|
||||||
|
q.Set("job_name", *opts.JobName)
|
||||||
|
}
|
||||||
|
if opts.NodesMax != nil {
|
||||||
|
q.Set("nodes_max", *opts.NodesMax)
|
||||||
|
}
|
||||||
|
if opts.NodesMin != nil {
|
||||||
|
q.Set("nodes_min", *opts.NodesMin)
|
||||||
|
}
|
||||||
|
if opts.Partition != nil {
|
||||||
|
q.Set("partition", *opts.Partition)
|
||||||
|
}
|
||||||
|
if opts.Qos != nil {
|
||||||
|
q.Set("qos", *opts.Qos)
|
||||||
|
}
|
||||||
|
if opts.Reason != nil {
|
||||||
|
q.Set("reason", *opts.Reason)
|
||||||
|
}
|
||||||
|
if opts.Reservation != nil {
|
||||||
|
q.Set("reservation", *opts.Reservation)
|
||||||
|
}
|
||||||
|
if opts.ReservationID != nil {
|
||||||
|
q.Set("reservation_id", *opts.ReservationID)
|
||||||
|
}
|
||||||
|
if opts.State != nil {
|
||||||
|
q.Set("state", *opts.State)
|
||||||
|
}
|
||||||
|
if opts.Step != nil {
|
||||||
|
q.Set("step", *opts.Step)
|
||||||
|
}
|
||||||
|
if opts.TimelimitMax != nil {
|
||||||
|
q.Set("timelimit_max", *opts.TimelimitMax)
|
||||||
|
}
|
||||||
|
if opts.TimelimitMin != nil {
|
||||||
|
q.Set("timelimit_min", *opts.TimelimitMin)
|
||||||
|
}
|
||||||
|
if opts.EndTime != nil {
|
||||||
|
q.Set("end_time", *opts.EndTime)
|
||||||
|
}
|
||||||
|
if opts.StartTime != nil {
|
||||||
|
q.Set("start_time", *opts.StartTime)
|
||||||
|
}
|
||||||
|
if opts.SubmitTime != nil {
|
||||||
|
q.Set("submit_time", *opts.SubmitTime)
|
||||||
|
}
|
||||||
|
if opts.Node != nil {
|
||||||
|
q.Set("node", *opts.Node)
|
||||||
|
}
|
||||||
|
if opts.Users != nil {
|
||||||
|
q.Set("users", *opts.Users)
|
||||||
|
}
|
||||||
|
if opts.Wckey != nil {
|
||||||
|
q.Set("wckey", *opts.Wckey)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiSlurmdbdJobsResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetJob retrieves info for a specific job from SlurmDBD.
|
||||||
|
func (s *SlurmdbJobsService) GetJob(ctx context.Context, jobID string) (*OpenapiSlurmdbdJobsResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/job/%s", jobID)
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiSlurmdbdJobsResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
246
internal/slurm/slurmdb_jobs_test.go
Normal file
246
internal/slurm/slurmdb_jobs_test.go
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbJobsService_GetJobs(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/jobs", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"jobs": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbJobs.GetJobs(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Jobs) != 0 {
|
||||||
|
t.Errorf("expected empty jobs, got %d", len(resp.Jobs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbJobsService_GetJobsWithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/jobs", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("users") != "alice,bob" {
|
||||||
|
t.Errorf("expected users=alice,bob, got %s", q.Get("users"))
|
||||||
|
}
|
||||||
|
if q.Get("account") != "science" {
|
||||||
|
t.Errorf("expected account=science, got %s", q.Get("account"))
|
||||||
|
}
|
||||||
|
if q.Get("cluster") != "cluster1" {
|
||||||
|
t.Errorf("expected cluster=cluster1, got %s", q.Get("cluster"))
|
||||||
|
}
|
||||||
|
if q.Get("state") != "RUNNING" {
|
||||||
|
t.Errorf("expected state=RUNNING, got %s", q.Get("state"))
|
||||||
|
}
|
||||||
|
if q.Get("start_time") != "1700000000" {
|
||||||
|
t.Errorf("expected start_time=1700000000, got %s", q.Get("start_time"))
|
||||||
|
}
|
||||||
|
if q.Get("partition") != "gpu" {
|
||||||
|
t.Errorf("expected partition=gpu, got %s", q.Get("partition"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"jobs": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetSlurmdbJobsOptions{
|
||||||
|
Users: Ptr("alice,bob"),
|
||||||
|
Account: Ptr("science"),
|
||||||
|
Cluster: Ptr("cluster1"),
|
||||||
|
State: Ptr("RUNNING"),
|
||||||
|
StartTime: Ptr("1700000000"),
|
||||||
|
Partition: Ptr("gpu"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbJobs.GetJobs(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbJobsService_GetJob(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/job/12345", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"jobs": [{"job_id": 12345, "name": "my-job"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbJobs.GetJob(context.Background(), "12345")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Jobs) != 1 {
|
||||||
|
t.Fatalf("expected 1 job, got %d", len(resp.Jobs))
|
||||||
|
}
|
||||||
|
if resp.Jobs[0].JobID == nil || *resp.Jobs[0].JobID != 12345 {
|
||||||
|
t.Errorf("expected job_id=12345, got %v", resp.Jobs[0].JobID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbJobsService_GetJobs_ServerError(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/jobs", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbJobs.GetJobs(context.Background(), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbJobsService_GetJob_ServerError(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/job/99999", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "job not found"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbJobs.GetJob(context.Background(), "99999")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbJobsService_GetJobs_AllQueryParams(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/jobs", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
expectedParams := map[string]string{
|
||||||
|
"account": "acct1",
|
||||||
|
"association": "assoc1",
|
||||||
|
"cluster": "cl1",
|
||||||
|
"constraints": "c1",
|
||||||
|
"cpus_max": "64",
|
||||||
|
"cpus_min": "1",
|
||||||
|
"scheduler_unset": "1",
|
||||||
|
"scheduled_on_submit": "1",
|
||||||
|
"scheduled_by_main": "1",
|
||||||
|
"scheduled_by_backfill": "1",
|
||||||
|
"job_started": "1",
|
||||||
|
"exit_code": "0",
|
||||||
|
"show_duplicates": "1",
|
||||||
|
"skip_steps": "1",
|
||||||
|
"disable_truncate_usage_time": "1",
|
||||||
|
"whole_hetjob": "1",
|
||||||
|
"disable_whole_hetjob": "0",
|
||||||
|
"disable_wait_for_result": "1",
|
||||||
|
"usage_time_as_submit_time": "1",
|
||||||
|
"show_batch_script": "1",
|
||||||
|
"show_job_environment": "1",
|
||||||
|
"format": "json",
|
||||||
|
"groups": "grp1",
|
||||||
|
"job_name": "jn1",
|
||||||
|
"nodes_max": "10",
|
||||||
|
"nodes_min": "1",
|
||||||
|
"partition": "part1",
|
||||||
|
"qos": "normal",
|
||||||
|
"reason": "r1",
|
||||||
|
"reservation": "res1",
|
||||||
|
"reservation_id": "100",
|
||||||
|
"state": "RUNNING",
|
||||||
|
"step": "0",
|
||||||
|
"timelimit_max": "3600",
|
||||||
|
"timelimit_min": "60",
|
||||||
|
"end_time": "1700001000",
|
||||||
|
"start_time": "1700000000",
|
||||||
|
"submit_time": "1699999000",
|
||||||
|
"node": "n1",
|
||||||
|
"users": "u1",
|
||||||
|
"wckey": "w1",
|
||||||
|
}
|
||||||
|
for k, v := range expectedParams {
|
||||||
|
got := q.Get(k)
|
||||||
|
if got != v {
|
||||||
|
t.Errorf("expected %s=%s, got %s", k, v, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"jobs": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetSlurmdbJobsOptions{
|
||||||
|
Account: Ptr("acct1"),
|
||||||
|
Association: Ptr("assoc1"),
|
||||||
|
Cluster: Ptr("cl1"),
|
||||||
|
Constraints: Ptr("c1"),
|
||||||
|
CpusMax: Ptr("64"),
|
||||||
|
CpusMin: Ptr("1"),
|
||||||
|
SchedulerUnset: Ptr("1"),
|
||||||
|
ScheduledOnSubmit: Ptr("1"),
|
||||||
|
ScheduledByMain: Ptr("1"),
|
||||||
|
ScheduledByBackfill: Ptr("1"),
|
||||||
|
JobStarted: Ptr("1"),
|
||||||
|
ExitCode: Ptr("0"),
|
||||||
|
ShowDuplicates: Ptr("1"),
|
||||||
|
SkipSteps: Ptr("1"),
|
||||||
|
DisableTruncateUsageTime: Ptr("1"),
|
||||||
|
WholeHetjob: Ptr("1"),
|
||||||
|
DisableWholeHetjob: Ptr("0"),
|
||||||
|
DisableWaitForResult: Ptr("1"),
|
||||||
|
UsageTimeAsSubmitTime: Ptr("1"),
|
||||||
|
ShowBatchScript: Ptr("1"),
|
||||||
|
ShowJobEnvironment: Ptr("1"),
|
||||||
|
Format: Ptr("json"),
|
||||||
|
Groups: Ptr("grp1"),
|
||||||
|
JobName: Ptr("jn1"),
|
||||||
|
NodesMax: Ptr("10"),
|
||||||
|
NodesMin: Ptr("1"),
|
||||||
|
Partition: Ptr("part1"),
|
||||||
|
Qos: Ptr("normal"),
|
||||||
|
Reason: Ptr("r1"),
|
||||||
|
Reservation: Ptr("res1"),
|
||||||
|
ReservationID: Ptr("100"),
|
||||||
|
State: Ptr("RUNNING"),
|
||||||
|
Step: Ptr("0"),
|
||||||
|
TimelimitMax: Ptr("3600"),
|
||||||
|
TimelimitMin: Ptr("60"),
|
||||||
|
EndTime: Ptr("1700001000"),
|
||||||
|
StartTime: Ptr("1700000000"),
|
||||||
|
SubmitTime: Ptr("1699999000"),
|
||||||
|
Node: Ptr("n1"),
|
||||||
|
Users: Ptr("u1"),
|
||||||
|
Wckey: Ptr("w1"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbJobs.GetJobs(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
117
internal/slurm/slurmdb_qos.go
Normal file
117
internal/slurm/slurmdb_qos.go
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetQosOptions struct {
|
||||||
|
Description *string `url:"description,omitempty"`
|
||||||
|
ID *string `url:"id,omitempty"`
|
||||||
|
Format *string `url:"format,omitempty"`
|
||||||
|
Name *string `url:"name,omitempty"`
|
||||||
|
PreemptMode *string `url:"preempt_mode,omitempty"`
|
||||||
|
WithDeleted *string `url:"with_deleted,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SlurmdbQosService) GetQosList(ctx context.Context, opts *GetQosOptions) (*OpenapiSlurmdbdQosResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/qos"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.Description != nil {
|
||||||
|
q.Set("description", *opts.Description)
|
||||||
|
}
|
||||||
|
if opts.ID != nil {
|
||||||
|
q.Set("id", *opts.ID)
|
||||||
|
}
|
||||||
|
if opts.Format != nil {
|
||||||
|
q.Set("format", *opts.Format)
|
||||||
|
}
|
||||||
|
if opts.Name != nil {
|
||||||
|
q.Set("name", *opts.Name)
|
||||||
|
}
|
||||||
|
if opts.PreemptMode != nil {
|
||||||
|
q.Set("preempt_mode", *opts.PreemptMode)
|
||||||
|
}
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiSlurmdbdQosResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SlurmdbQosService) GetQos(ctx context.Context, qosName string, opts *GetQosOptions) (*OpenapiSlurmdbdQosResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/qos/%s", qosName)
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiSlurmdbdQosResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SlurmdbQosService) PostQos(ctx context.Context, body *OpenapiSlurmdbdQosResp) (*OpenapiSlurmdbdQosResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/qos"
|
||||||
|
req, err := s.client.NewRequest("POST", path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiSlurmdbdQosResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SlurmdbQosService) DeleteQos(ctx context.Context, qosName string) (*OpenapiSlurmdbdQosRemovedResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/qos/%s", qosName)
|
||||||
|
req, err := s.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiSlurmdbdQosRemovedResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
185
internal/slurm/slurmdb_qos_test.go
Normal file
185
internal/slurm/slurmdb_qos_test.go
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbQosService_GetQosList(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/qos", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"qos": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbQos.GetQosList(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbQosService_GetQosList_WithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/qos", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("description") != "test-desc" {
|
||||||
|
t.Errorf("expected description=test-desc, got %s", q.Get("description"))
|
||||||
|
}
|
||||||
|
if q.Get("id") != "1,2" {
|
||||||
|
t.Errorf("expected id=1,2, got %s", q.Get("id"))
|
||||||
|
}
|
||||||
|
if q.Get("name") != "normal,debug" {
|
||||||
|
t.Errorf("expected name=normal,debug, got %s", q.Get("name"))
|
||||||
|
}
|
||||||
|
if q.Get("with_deleted") != "true" {
|
||||||
|
t.Errorf("expected with_deleted=true, got %s", q.Get("with_deleted"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"qos": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetQosOptions{
|
||||||
|
Description: Ptr("test-desc"),
|
||||||
|
ID: Ptr("1,2"),
|
||||||
|
Name: Ptr("normal,debug"),
|
||||||
|
WithDeleted: Ptr("true"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbQos.GetQosList(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbQosService_GetQos(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/qos/normal", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"qos": [{"name": "normal", "description": "normal QOS"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbQos.GetQos(context.Background(), "normal", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Qos) != 1 {
|
||||||
|
t.Fatalf("expected 1 qos, got %d", len(resp.Qos))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbQosService_GetQos_WithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/qos/normal", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("with_deleted") != "true" {
|
||||||
|
t.Errorf("expected with_deleted=true, got %s", q.Get("with_deleted"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"qos": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetQosOptions{
|
||||||
|
WithDeleted: Ptr("true"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbQos.GetQos(context.Background(), "normal", opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbQosService_PostQos(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/qos", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
if ct := r.Header.Get("Content-Type"); ct != "application/json" {
|
||||||
|
t.Errorf("expected Content-Type application/json, got %s", ct)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"qos": [{"name": "new-qos"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
body := &OpenapiSlurmdbdQosResp{}
|
||||||
|
resp, _, err := client.SlurmdbQos.PostQos(context.Background(), body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Qos) != 1 {
|
||||||
|
t.Errorf("expected 1 qos, got %d", len(resp.Qos))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbQosService_DeleteQos(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/qos/old-qos", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
fmt.Fprint(w, `{"removed_qos": ["old-qos"]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbQos.DeleteQos(context.Background(), "old-qos")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.RemovedQos) != 1 {
|
||||||
|
t.Fatalf("expected 1 removed qos, got %d", len(resp.RemovedQos))
|
||||||
|
}
|
||||||
|
if resp.RemovedQos[0] != "old-qos" {
|
||||||
|
t.Errorf("expected removed_qos=old-qos, got %s", resp.RemovedQos[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbQosService_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/qos", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbQos.GetQosList(context.Background(), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 500 response")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "500") {
|
||||||
|
t.Errorf("expected error to contain 500, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
35
internal/slurm/slurmdb_tres.go
Normal file
35
internal/slurm/slurmdb_tres.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
// GetTres returns TRES information.
|
||||||
|
func (s *SlurmdbTresService) GetTres(ctx context.Context) (*OpenapiTresResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/tres"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiTresResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostTres updates TRES information.
|
||||||
|
func (s *SlurmdbTresService) PostTres(ctx context.Context, tres *OpenapiTresResp) (*OpenapiTresResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/tres"
|
||||||
|
req, err := s.client.NewRequest("POST", path, tres)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiTresResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
82
internal/slurm/slurmdb_tres_test.go
Normal file
82
internal/slurm/slurmdb_tres_test.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbTresService_GetTres(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/tres", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"TRES": [{"type": "cpu", "id": 1, "count": 100}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbTres.GetTres(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.TRES) != 1 {
|
||||||
|
t.Fatalf("expected 1 TRES entry, got %d", len(resp.TRES))
|
||||||
|
}
|
||||||
|
if *resp.TRES[0].Type != "cpu" {
|
||||||
|
t.Errorf("expected TRES type 'cpu', got %q", *resp.TRES[0].Type)
|
||||||
|
}
|
||||||
|
if *resp.TRES[0].ID != 1 {
|
||||||
|
t.Errorf("expected TRES id 1, got %d", *resp.TRES[0].ID)
|
||||||
|
}
|
||||||
|
if *resp.TRES[0].Count != 100 {
|
||||||
|
t.Errorf("expected TRES count 100, got %d", *resp.TRES[0].Count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbTresService_PostTres(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/tres", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
fmt.Fprint(w, `{"TRES": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbTres.PostTres(context.Background(), &OpenapiTresResp{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.TRES) != 0 {
|
||||||
|
t.Errorf("expected empty TRES, got %d entries", len(resp.TRES))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbTresService_GetTres_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/tres", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbTres.GetTres(context.Background())
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 500 response")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "500") {
|
||||||
|
t.Errorf("expected error to contain 500, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
155
internal/slurm/slurmdb_users.go
Normal file
155
internal/slurm/slurmdb_users.go
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetUsersOptions specifies optional parameters for GetUsers and GetUser.
|
||||||
|
type GetUsersOptions struct {
|
||||||
|
AdminLevel *string `url:"admin_level,omitempty"`
|
||||||
|
DefaultAccount *string `url:"default_account,omitempty"`
|
||||||
|
DefaultWckey *string `url:"default_wckey,omitempty"`
|
||||||
|
WithAssocs *string `url:"with_assocs,omitempty"`
|
||||||
|
WithCoords *string `url:"with_coords,omitempty"`
|
||||||
|
WithDeleted *string `url:"with_deleted,omitempty"`
|
||||||
|
WithWckeys *string `url:"with_wckeys,omitempty"`
|
||||||
|
WithoutDefaults *string `url:"without_defaults,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsers lists all users.
|
||||||
|
func (s *SlurmdbUsersService) GetUsers(ctx context.Context, opts *GetUsersOptions) (*OpenapiUsersResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/users"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.AdminLevel != nil {
|
||||||
|
q.Set("admin_level", *opts.AdminLevel)
|
||||||
|
}
|
||||||
|
if opts.DefaultAccount != nil {
|
||||||
|
q.Set("default_account", *opts.DefaultAccount)
|
||||||
|
}
|
||||||
|
if opts.DefaultWckey != nil {
|
||||||
|
q.Set("default_wckey", *opts.DefaultWckey)
|
||||||
|
}
|
||||||
|
if opts.WithAssocs != nil {
|
||||||
|
q.Set("with_assocs", *opts.WithAssocs)
|
||||||
|
}
|
||||||
|
if opts.WithCoords != nil {
|
||||||
|
q.Set("with_coords", *opts.WithCoords)
|
||||||
|
}
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
if opts.WithWckeys != nil {
|
||||||
|
q.Set("with_wckeys", *opts.WithWckeys)
|
||||||
|
}
|
||||||
|
if opts.WithoutDefaults != nil {
|
||||||
|
q.Set("without_defaults", *opts.WithoutDefaults)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiUsersResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUser gets a single user by name.
|
||||||
|
func (s *SlurmdbUsersService) GetUser(ctx context.Context, userName string, opts *GetUsersOptions) (*OpenapiUsersResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/user/%s", userName)
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
if opts.WithAssocs != nil {
|
||||||
|
q.Set("with_assocs", *opts.WithAssocs)
|
||||||
|
}
|
||||||
|
if opts.WithCoords != nil {
|
||||||
|
q.Set("with_coords", *opts.WithCoords)
|
||||||
|
}
|
||||||
|
if opts.WithWckeys != nil {
|
||||||
|
q.Set("with_wckeys", *opts.WithWckeys)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiUsersResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostUsers updates users.
|
||||||
|
func (s *SlurmdbUsersService) PostUsers(ctx context.Context, body *OpenapiUsersResp) (*OpenapiUsersResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/users"
|
||||||
|
req, err := s.client.NewRequest("POST", path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiUsersResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostUsersAssociation adds users with conditional association.
|
||||||
|
func (s *SlurmdbUsersService) PostUsersAssociation(ctx context.Context, body *OpenapiUsersAddCondResp) (*OpenapiUsersAddCondRespStr, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/users_association"
|
||||||
|
req, err := s.client.NewRequest("POST", path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiUsersAddCondRespStr
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUser deletes a user by name.
|
||||||
|
func (s *SlurmdbUsersService) DeleteUser(ctx context.Context, userName string) (*OpenapiResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/user/%s", userName)
|
||||||
|
req, err := s.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
160
internal/slurm/slurmdb_users_test.go
Normal file
160
internal/slurm/slurmdb_users_test.go
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbUsersService_GetUsers(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/users", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"users": [{"name": "testuser"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbUsers.GetUsers(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbUsersService_GetUsersWithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/users", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
if r.URL.Query().Get("with_deleted") != "true" {
|
||||||
|
t.Error("expected with_deleted=true query param")
|
||||||
|
}
|
||||||
|
if r.URL.Query().Get("with_assocs") != "true" {
|
||||||
|
t.Error("expected with_assocs=true query param")
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"users": [{"name": "testuser"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
deleted := "true"
|
||||||
|
assocs := "true"
|
||||||
|
opts := &GetUsersOptions{WithDeleted: &deleted, WithAssocs: &assocs}
|
||||||
|
resp, _, err := client.SlurmdbUsers.GetUsers(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbUsersService_GetUser(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/user/testuser", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"users": [{"name": "testuser"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbUsers.GetUser(context.Background(), "testuser", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbUsersService_PostUsers(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/users", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
fmt.Fprint(w, `{"users": [{"name": "testuser"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
body := &OpenapiUsersResp{}
|
||||||
|
resp, _, err := client.SlurmdbUsers.PostUsers(context.Background(), body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbUsersService_PostUsersAssociation(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/users_association", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
fmt.Fprint(w, `{"added_users": "user1,user2"}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
body := &OpenapiUsersAddCondResp{}
|
||||||
|
resp, _, err := client.SlurmdbUsers.PostUsersAssociation(context.Background(), body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if resp.AddedUsers == nil {
|
||||||
|
t.Fatal("expected non-nil AddedUsers")
|
||||||
|
}
|
||||||
|
if *resp.AddedUsers != "user1,user2" {
|
||||||
|
t.Errorf("expected added_users 'user1,user2', got %s", *resp.AddedUsers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbUsersService_DeleteUser(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/user/testuser", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
fmt.Fprint(w, `{"meta": {"plugin": {"type": "openapi/v0.0.40"}}}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbUsers.DeleteUser(context.Background(), "testuser")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbUsersService_GetUsers_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/users", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "internal error"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbUsers.GetUsers(context.Background(), nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 500 response")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "500") {
|
||||||
|
t.Errorf("expected error to contain 500, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
125
internal/slurm/slurmdb_wckeys.go
Normal file
125
internal/slurm/slurmdb_wckeys.go
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetWckeysOptions specifies optional parameters for GetWckeys.
|
||||||
|
type GetWckeysOptions struct {
|
||||||
|
Cluster *string `url:"cluster,omitempty"`
|
||||||
|
Format *string `url:"format,omitempty"`
|
||||||
|
ID *string `url:"id,omitempty"`
|
||||||
|
Name *string `url:"name,omitempty"`
|
||||||
|
OnlyDefaults *string `url:"only_defaults,omitempty"`
|
||||||
|
UsageEnd *string `url:"usage_end,omitempty"`
|
||||||
|
UsageStart *string `url:"usage_start,omitempty"`
|
||||||
|
User *string `url:"user,omitempty"`
|
||||||
|
WithUsage *string `url:"with_usage,omitempty"`
|
||||||
|
WithDeleted *string `url:"with_deleted,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWckeys lists all wckeys.
|
||||||
|
func (s *SlurmdbWckeysService) GetWckeys(ctx context.Context, opts *GetWckeysOptions) (*OpenapiWckeyResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/wckeys"
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts != nil {
|
||||||
|
u, parseErr := url.Parse(req.URL.String())
|
||||||
|
if parseErr != nil {
|
||||||
|
return nil, nil, parseErr
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
if opts.Cluster != nil {
|
||||||
|
q.Set("cluster", *opts.Cluster)
|
||||||
|
}
|
||||||
|
if opts.Format != nil {
|
||||||
|
q.Set("format", *opts.Format)
|
||||||
|
}
|
||||||
|
if opts.ID != nil {
|
||||||
|
q.Set("id", *opts.ID)
|
||||||
|
}
|
||||||
|
if opts.Name != nil {
|
||||||
|
q.Set("name", *opts.Name)
|
||||||
|
}
|
||||||
|
if opts.OnlyDefaults != nil {
|
||||||
|
q.Set("only_defaults", *opts.OnlyDefaults)
|
||||||
|
}
|
||||||
|
if opts.UsageEnd != nil {
|
||||||
|
q.Set("usage_end", *opts.UsageEnd)
|
||||||
|
}
|
||||||
|
if opts.UsageStart != nil {
|
||||||
|
q.Set("usage_start", *opts.UsageStart)
|
||||||
|
}
|
||||||
|
if opts.User != nil {
|
||||||
|
q.Set("user", *opts.User)
|
||||||
|
}
|
||||||
|
if opts.WithUsage != nil {
|
||||||
|
q.Set("with_usage", *opts.WithUsage)
|
||||||
|
}
|
||||||
|
if opts.WithDeleted != nil {
|
||||||
|
q.Set("with_deleted", *opts.WithDeleted)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiWckeyResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWckey gets a single wckey by ID.
|
||||||
|
func (s *SlurmdbWckeysService) GetWckey(ctx context.Context, wckeyID string) (*OpenapiWckeyResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/wckey/%s", wckeyID)
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiWckeyResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostWckeys adds wckeys.
|
||||||
|
func (s *SlurmdbWckeysService) PostWckeys(ctx context.Context, body *OpenapiWckeyResp) (*OpenapiResp, *Response, error) {
|
||||||
|
path := "slurmdb/v0.0.40/wckeys"
|
||||||
|
req, err := s.client.NewRequest("POST", path, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWckey deletes a wckey by ID.
|
||||||
|
func (s *SlurmdbWckeysService) DeleteWckey(ctx context.Context, wckeyID string) (*OpenapiWckeyRemovedResp, *Response, error) {
|
||||||
|
path := fmt.Sprintf("slurmdb/v0.0.40/wckey/%s", wckeyID)
|
||||||
|
req, err := s.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result OpenapiWckeyRemovedResp
|
||||||
|
resp, err := s.client.Do(ctx, req, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return &result, resp, nil
|
||||||
|
}
|
||||||
155
internal/slurm/slurmdb_wckeys_test.go
Normal file
155
internal/slurm/slurmdb_wckeys_test.go
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
package slurm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlurmdbWckeysService_GetWckeys(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/wckeys", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"wckeys": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbWckeys.GetWckeys(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Wckeys) != 0 {
|
||||||
|
t.Errorf("expected empty wckeys, got %d", len(resp.Wckeys))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbWckeysService_GetWckeys_WithOptions(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/wckeys", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("cluster") != "test-cluster" {
|
||||||
|
t.Errorf("expected cluster=test-cluster, got %s", q.Get("cluster"))
|
||||||
|
}
|
||||||
|
if q.Get("name") != "mykey" {
|
||||||
|
t.Errorf("expected name=mykey, got %s", q.Get("name"))
|
||||||
|
}
|
||||||
|
if q.Get("with_deleted") != "true" {
|
||||||
|
t.Errorf("expected with_deleted=true, got %s", q.Get("with_deleted"))
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{"wckeys": []}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
opts := &GetWckeysOptions{
|
||||||
|
Cluster: Ptr("test-cluster"),
|
||||||
|
Name: Ptr("mykey"),
|
||||||
|
WithDeleted: Ptr("true"),
|
||||||
|
}
|
||||||
|
resp, _, err := client.SlurmdbWckeys.GetWckeys(context.Background(), opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbWckeysService_GetWckey(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/wckey/42", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "GET")
|
||||||
|
fmt.Fprint(w, `{"wckeys": [{"name": "wckey42"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbWckeys.GetWckey(context.Background(), "42")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.Wckeys) != 1 {
|
||||||
|
t.Fatalf("expected 1 wckey, got %d", len(resp.Wckeys))
|
||||||
|
}
|
||||||
|
if resp.Wckeys[0].Name == nil || *resp.Wckeys[0].Name != "wckey42" {
|
||||||
|
t.Errorf("expected name=wckey42, got %v", resp.Wckeys[0].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbWckeysService_PostWckeys(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/wckeys", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "POST")
|
||||||
|
if ct := r.Header.Get("Content-Type"); ct != "application/json" {
|
||||||
|
t.Errorf("expected Content-Type application/json, got %s", ct)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, `{}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
body := &OpenapiWckeyResp{}
|
||||||
|
resp, _, err := client.SlurmdbWckeys.PostWckeys(context.Background(), body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbWckeysService_DeleteWckey(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/wckey/42", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
testMethod(t, r, "DELETE")
|
||||||
|
fmt.Fprint(w, `{"deleted_wckeys": ["wckey42"]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
resp, _, err := client.SlurmdbWckeys.DeleteWckey(context.Background(), "42")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response")
|
||||||
|
}
|
||||||
|
if len(resp.DeletedWckeys) != 1 || resp.DeletedWckeys[0] != "wckey42" {
|
||||||
|
t.Errorf("expected deleted_wckeys=[wckey42], got %v", resp.DeletedWckeys)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlurmdbWckeysService_GetWckey_Error(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/slurmdb/v0.0.40/wckey/999", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
fmt.Fprint(w, `{"errors": [{"error": "wckey not found"}]}`)
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client, _ := NewClient(server.URL, nil)
|
||||||
|
_, _, err := client.SlurmdbWckeys.GetWckey(context.Background(), "999")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error for 404 response")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "404") {
|
||||||
|
t.Errorf("expected error to contain 404, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user