style(frontend): gofmt the apiserver and xcecli sources
Formatting only (gofmt -w on the 29 non-vendored, non-generated files gofmt -l reported); swag-generated apiserver/docs/docs.go left as is. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b57ce6d6a9
commit
3615c7c0fb
29 changed files with 1280 additions and 1285 deletions
|
|
@ -23,10 +23,10 @@ config_file:
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
user string
|
user string
|
||||||
pass string
|
pass string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"valid admin", "admin", "secret", false},
|
{"valid admin", "admin", "secret", false},
|
||||||
{"valid viewer", "viewer", "pass", false},
|
{"valid viewer", "viewer", "pass", false},
|
||||||
|
|
|
||||||
|
|
@ -515,4 +515,4 @@ func TestIntegration_CrossFeature_SequentialConfigPushes(t *testing.T) {
|
||||||
if hb := atomic.LoadInt32(&heartbeatIntervalSecs); hb != 60 {
|
if hb := atomic.LoadInt32(&heartbeatIntervalSecs); hb != 60 {
|
||||||
t.Errorf("heartbeatIntervalSecs = %d, want 60", hb)
|
t.Errorf("heartbeatIntervalSecs = %d, want 60", hb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "apiserver/docs"
|
|
||||||
"apiserver/backend"
|
"apiserver/backend"
|
||||||
"apiserver/backend/auth"
|
"apiserver/backend/auth"
|
||||||
|
_ "apiserver/docs"
|
||||||
"apiserver/middleware"
|
"apiserver/middleware"
|
||||||
"apiserver/router"
|
"apiserver/router"
|
||||||
"apiserver/store"
|
"apiserver/store"
|
||||||
|
|
|
||||||
|
|
@ -44,16 +44,16 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SUCCESS_CODE = 200
|
SUCCESS_CODE = 200
|
||||||
CREATED = 201
|
CREATED = 201
|
||||||
ACCEPTED = 202
|
ACCEPTED = 202
|
||||||
StatusPartialContent = 206
|
StatusPartialContent = 206
|
||||||
ERROR_CODE = 500
|
ERROR_CODE = 500
|
||||||
INVALID_PARAMS_CODE = 400
|
INVALID_PARAMS_CODE = 400
|
||||||
ERROR_AUTH_CHECK_TOKEN_CODE = 401
|
ERROR_AUTH_CHECK_TOKEN_CODE = 401
|
||||||
ERROR_AUTH_CODE = 403
|
ERROR_AUTH_CODE = 403
|
||||||
ERROR_NOT_FOUND_CODE = 404
|
ERROR_NOT_FOUND_CODE = 404
|
||||||
ERROR_TOO_MANY_REQUESTS_CODE = 429
|
ERROR_TOO_MANY_REQUESTS_CODE = 429
|
||||||
|
|
||||||
//read file error
|
//read file error
|
||||||
ERROR_READ_FILE_CODE = 501
|
ERROR_READ_FILE_CODE = 501
|
||||||
|
|
|
||||||
|
|
@ -675,4 +675,4 @@ func TestIntegration_SpecialCharactersInHostname(t *testing.T) {
|
||||||
if hostnameVal != xssHostname {
|
if hostnameVal != xssHostname {
|
||||||
t.Errorf("hostname round-trip: got %q, want %q", hostnameVal, xssHostname)
|
t.Errorf("hostname round-trip: got %q, want %q", hostnameVal, xssHostname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
//TODO: Need assign clusterID globally.
|
//TODO: Need assign clusterID globally.
|
||||||
clusterID = 1
|
clusterID = 1
|
||||||
apiserverID = 0
|
apiserverID = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -3190,4 +3190,3 @@ func GetHostList(hosts []string) ([]string, error) {
|
||||||
}
|
}
|
||||||
return execHosts, nil
|
return execHosts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"apiserver/backend"
|
"apiserver/backend"
|
||||||
"apiserver/models"
|
"apiserver/models"
|
||||||
"apiserver/store"
|
"apiserver/store"
|
||||||
"apiserver/utils"
|
"apiserver/utils"
|
||||||
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -242,4 +242,3 @@ func parseJobIDParam(jobidStr string) (models.JobInfo, error) {
|
||||||
ArrayIdx: 0, // peek defaults to base job; array idx can be added later
|
ArrayIdx: 0, // peek defaults to base job; array idx can be added later
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ func TestGetJobOutput_DefaultPathFallback(t *testing.T) {
|
||||||
// Use a real-ish packed job ID: cluster=1, apiserver=0, ts=1778311965, seq=0
|
// Use a real-ish packed job ID: cluster=1, apiserver=0, ts=1778311965, seq=0
|
||||||
// FormatJobID → "1-0-1778311965-0"
|
// FormatJobID → "1-0-1778311965-0"
|
||||||
// WorkerDefaultOutputPath → "/tmp/job_1-0-1778311965-0_task0.out"
|
// WorkerDefaultOutputPath → "/tmp/job_1-0-1778311965-0_task0.out"
|
||||||
const uniqueID = int64(0x0100000006A04BDD<<0) // MakeJobID(1,0,1778311965,0,0)
|
const uniqueID = int64(0x0100000006A04BDD << 0) // MakeJobID(1,0,1778311965,0,0)
|
||||||
// Use backend.MakeJobID directly for clarity; compute inline:
|
// Use backend.MakeJobID directly for clarity; compute inline:
|
||||||
// clusterID=1 at bit 56, timestamp=1778311965 at bit 20
|
// clusterID=1 at bit 56, timestamp=1778311965 at bit 20
|
||||||
// packed = (1 << 56) | (1778311965 << 20)
|
// packed = (1 << 56) | (1778311965 << 20)
|
||||||
|
|
@ -512,4 +512,3 @@ func TestGetJobOutput_DoneJob(t *testing.T) {
|
||||||
t.Errorf("job_status = %q, want DONE", resp.Data.JobStatus)
|
t.Errorf("job_status = %q, want DONE", resp.Data.JobStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,46 +7,46 @@ import (
|
||||||
|
|
||||||
func TestClusterInfo_NewFields(t *testing.T) {
|
func TestClusterInfo_NewFields(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
cluster ClusterInfo
|
cluster ClusterInfo
|
||||||
field string
|
field string
|
||||||
want interface{}
|
want interface{}
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "HeartbeatInterval field exists and serializes",
|
name: "HeartbeatInterval field exists and serializes",
|
||||||
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 30},
|
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 30},
|
||||||
field: "heartbeat_interval",
|
field: "heartbeat_interval",
|
||||||
want: float64(30),
|
want: float64(30),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Vcpus field exists and serializes",
|
name: "Vcpus field exists and serializes",
|
||||||
cluster: ClusterInfo{ClusterName: "test", Vcpus: 16},
|
cluster: ClusterInfo{ClusterName: "test", Vcpus: 16},
|
||||||
field: "vcpus",
|
field: "vcpus",
|
||||||
want: float64(16),
|
want: float64(16),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "InactiveHeartbeatCount field exists and serializes",
|
name: "InactiveHeartbeatCount field exists and serializes",
|
||||||
cluster: ClusterInfo{ClusterName: "test", InactiveHeartbeatCount: 3},
|
cluster: ClusterInfo{ClusterName: "test", InactiveHeartbeatCount: 3},
|
||||||
field: "inactive_heartbeat_count",
|
field: "inactive_heartbeat_count",
|
||||||
want: float64(3),
|
want: float64(3),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "HeartbeatInterval zero value serializes as 0 not omitted",
|
name: "HeartbeatInterval zero value serializes as 0 not omitted",
|
||||||
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
||||||
field: "heartbeat_interval",
|
field: "heartbeat_interval",
|
||||||
want: float64(0),
|
want: float64(0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Vcpus zero value serializes as 0 not omitted",
|
name: "Vcpus zero value serializes as 0 not omitted",
|
||||||
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
||||||
field: "vcpus",
|
field: "vcpus",
|
||||||
want: float64(0),
|
want: float64(0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "InactiveHeartbeatCount zero value serializes as 0 not omitted",
|
name: "InactiveHeartbeatCount zero value serializes as 0 not omitted",
|
||||||
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
cluster: ClusterInfo{ClusterName: "test", HeartbeatInterval: 0, Vcpus: 0, InactiveHeartbeatCount: 0},
|
||||||
field: "inactive_heartbeat_count",
|
field: "inactive_heartbeat_count",
|
||||||
want: float64(0),
|
want: float64(0),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,4 +122,4 @@ func mapKeys(m map[string]interface{}) []string {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CONTROL_JOB = 1
|
CONTROL_JOB = 1
|
||||||
CONTROL_HOST = 2
|
CONTROL_HOST = 2
|
||||||
CONTROL_QUEUE = 3
|
CONTROL_QUEUE = 3
|
||||||
CONTROL_CLUSTER = 4
|
CONTROL_CLUSTER = 4
|
||||||
CONTROL_DEBUG = 5
|
CONTROL_DEBUG = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActionControl struct {
|
type ActionControl struct {
|
||||||
TargetType int `json:"target_type"`
|
TargetType int `json:"target_type"`
|
||||||
ActionType int `json:"action_type"`
|
ActionType int `json:"action_type"`
|
||||||
Content Jsonb `json:"content"`
|
Content Jsonb `json:"content"`
|
||||||
SubmitTime int64 `json:"submit_time"`
|
SubmitTime int64 `json:"submit_time"`
|
||||||
Submitter string `json:"submitter"`
|
Submitter string `json:"submitter"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,9 @@ type HostInfo struct {
|
||||||
NumSSusp int `json:"num_ssusp"`
|
NumSSusp int `json:"num_ssusp"`
|
||||||
NumUSusp int `json:"num_ususp"`
|
NumUSusp int `json:"num_ususp"`
|
||||||
//NumRsv int `json:"num_rsv"`
|
//NumRsv int `json:"num_rsv"`
|
||||||
NumDone int `json:"num_done"`
|
NumDone int `json:"num_done"`
|
||||||
Topology string `json:"topology"` // JSONB
|
Topology string `json:"topology"` // JSONB
|
||||||
SchedStop string `json:"sched_stop"` // JSONB
|
SchedStop string `json:"sched_stop"` // JSONB
|
||||||
ResourceValues []ResourceDistributionInfo `json:"resource_values"` // per-worker resource values
|
ResourceValues []ResourceDistributionInfo `json:"resource_values"` // per-worker resource values
|
||||||
//RealLoad string `json:"real_load"` // JSONB
|
//RealLoad string `json:"real_load"` // JSONB
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,4 +68,4 @@ func TestHostStateStr(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -591,32 +591,32 @@ type ArrayJobInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type JobAdditionalFields struct {
|
type JobAdditionalFields struct {
|
||||||
JobID int64 `json:"job_id"`
|
JobID int64 `json:"job_id"`
|
||||||
SubmitUser string `json:"submit_user"`
|
SubmitUser string `json:"submit_user"`
|
||||||
JobStatus int `json:"job_status"`
|
JobStatus int `json:"job_status"`
|
||||||
SubmitTime int64 `json:"submit_time"`
|
SubmitTime int64 `json:"submit_time"`
|
||||||
FromHost string `json:"from_host"`
|
FromHost string `json:"from_host"`
|
||||||
ExecHosts string `json:"exec_hosts"`
|
ExecHosts string `json:"exec_hosts"`
|
||||||
|
|
||||||
StartTime int64 `json:"start_time"`
|
StartTime int64 `json:"start_time"`
|
||||||
EndTime int64 `json:"end_time"`
|
EndTime int64 `json:"end_time"`
|
||||||
JobRusage Jsonb `json:"job_rusage"`
|
JobRusage Jsonb `json:"job_rusage"`
|
||||||
MaxMem float64 `json:"max_mem"`
|
MaxMem float64 `json:"max_mem"`
|
||||||
AvgMem float64 `json:"avg_mem"`
|
AvgMem float64 `json:"avg_mem"`
|
||||||
UsedMem float64 `json:"used_mem"`
|
UsedMem float64 `json:"used_mem"`
|
||||||
CPUTime int `json:"cpu_time"`
|
CPUTime int `json:"cpu_time"`
|
||||||
PeakCPUTime int `json:"peak_cpu_time"`
|
PeakCPUTime int `json:"peak_cpu_time"`
|
||||||
PeakCPUDuration float64 `json:"peak_cpu_duration"`
|
PeakCPUDuration float64 `json:"peak_cpu_duration"`
|
||||||
MemEfficiency float64 `json:"mem_efficiency"` // Memory efficiency in percentage
|
MemEfficiency float64 `json:"mem_efficiency"` // Memory efficiency in percentage
|
||||||
AvgCPUEfficiency float64 `json:"avg_cpu_efficiency"` // Average CPU efficiency in percentage
|
AvgCPUEfficiency float64 `json:"avg_cpu_efficiency"` // Average CPU efficiency in percentage
|
||||||
PeakCPUEfficiency float64 `json:"peak_cpu_efficiency"` // Peak CPU efficiency in percentage
|
PeakCPUEfficiency float64 `json:"peak_cpu_efficiency"` // Peak CPU efficiency in percentage
|
||||||
NumHosts int `json:"num_hosts"` // Number of hosts used by the job
|
NumHosts int `json:"num_hosts"` // Number of hosts used by the job
|
||||||
FirstHost string `json:"first_host"` // First host where the job ran
|
FirstHost string `json:"first_host"` // First host where the job ran
|
||||||
AllocSlot string `json:"alloc_slots"` // Allocated slot information
|
AllocSlot string `json:"alloc_slots"` // Allocated slot information
|
||||||
PIDInfo Jsonb `json:"pid_info"`
|
PIDInfo Jsonb `json:"pid_info"`
|
||||||
Pids []int `json:"pids"` // List of process IDs associated with the job
|
Pids []int `json:"pids"` // List of process IDs associated with the job
|
||||||
Pgids []int `json:"pgids"` // List of process group IDs associated with the job
|
Pgids []int `json:"pgids"` // List of process group IDs associated with the job
|
||||||
InteractiveJobURL string `json:"interactive_job_url"`
|
InteractiveJobURL string `json:"interactive_job_url"`
|
||||||
// CoreLimit/MemLimit: JobInfo has no equivalent field (these are
|
// CoreLimit/MemLimit: JobInfo has no equivalent field (these are
|
||||||
// submission-time resource limits, not job-state fields), but xcecli's
|
// submission-time resource limits, not job-state fields), but xcecli's
|
||||||
// JobFieldsMap accepts them as valid -o/-l display fields (bug-1674) --
|
// JobFieldsMap accepts them as valid -o/-l display fields (bug-1674) --
|
||||||
|
|
|
||||||
|
|
@ -1,139 +1,139 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
type ValueType int
|
type ValueType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
STRING ValueType = iota // Bool value
|
STRING ValueType = iota // Bool value
|
||||||
NUMERIC // Numeric value
|
NUMERIC // Numeric value
|
||||||
BOOLEAN // String value
|
BOOLEAN // String value
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns the string representation of ValueType
|
// String returns the string representation of ValueType
|
||||||
func (v ValueType) String() string {
|
func (v ValueType) String() string {
|
||||||
switch v {
|
switch v {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
return "Boolean"
|
return "Boolean"
|
||||||
case NUMERIC:
|
case NUMERIC:
|
||||||
return "Numeric"
|
return "Numeric"
|
||||||
case STRING:
|
case STRING:
|
||||||
return "String"
|
return "String"
|
||||||
default:
|
default:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrderType int
|
type OrderType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
INCR OrderType = iota
|
INCR OrderType = iota
|
||||||
DECR
|
DECR
|
||||||
NA
|
NA
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns the string representation of OrderType
|
// String returns the string representation of OrderType
|
||||||
func (o OrderType) String() string {
|
func (o OrderType) String() string {
|
||||||
switch o {
|
switch o {
|
||||||
case INCR:
|
case INCR:
|
||||||
return "Incr"
|
return "Incr"
|
||||||
case DECR:
|
case DECR:
|
||||||
return "Decr"
|
return "Decr"
|
||||||
case NA:
|
case NA:
|
||||||
return "NA"
|
return "NA"
|
||||||
default:
|
default:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var RESOURCE_DEFAULT_COLUMN = []string{
|
var RESOURCE_DEFAULT_COLUMN = []string{
|
||||||
"res_name",
|
"res_name",
|
||||||
"description",
|
"description",
|
||||||
"value_type",
|
"value_type",
|
||||||
"order_type",
|
"order_type",
|
||||||
"flag",
|
"flag",
|
||||||
"interval",
|
"interval",
|
||||||
}
|
}
|
||||||
|
|
||||||
var RESOURCE_DISTRIBUTION_DEFAULT_COLUMN = []string{
|
var RESOURCE_DISTRIBUTION_DEFAULT_COLUMN = []string{
|
||||||
"res_name",
|
"res_name",
|
||||||
"numeric_value",
|
"numeric_value",
|
||||||
"location",
|
"location",
|
||||||
"is_dynamic",
|
"is_dynamic",
|
||||||
}
|
}
|
||||||
|
|
||||||
var RESOURCE_DEFINITION_DEFAULT_COLUMN = []string{
|
var RESOURCE_DEFINITION_DEFAULT_COLUMN = []string{
|
||||||
"res_name",
|
"res_name",
|
||||||
"description",
|
"description",
|
||||||
"value_type",
|
"value_type",
|
||||||
"order_type",
|
"order_type",
|
||||||
"flag",
|
"flag",
|
||||||
"interval",
|
"interval",
|
||||||
}
|
}
|
||||||
|
|
||||||
var ResourceFieldMappings = map[string]string{
|
var ResourceFieldMappings = map[string]string{
|
||||||
// API field name → struct field name
|
// API field name → struct field name
|
||||||
"value": "numeric_value",
|
"value": "numeric_value",
|
||||||
}
|
}
|
||||||
|
|
||||||
var ResourcesAvailableTypes = []string{"static", "dynamic"}
|
var ResourcesAvailableTypes = []string{"static", "dynamic"}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BUILTIN = 0x01
|
BUILTIN = 0x01
|
||||||
DYNAMIC = 0x02
|
DYNAMIC = 0x02
|
||||||
RELEASE = 0x20
|
RELEASE = 0x20
|
||||||
CONSUMABLE = 0x80
|
CONSUMABLE = 0x80
|
||||||
)
|
)
|
||||||
|
|
||||||
type FlagValue int
|
type FlagValue int
|
||||||
|
|
||||||
// ToJSON returns the JSON object representation of FlagValue
|
// ToJSON returns the JSON object representation of FlagValue
|
||||||
func (f FlagValue) ToJSON() map[string]bool {
|
func (f FlagValue) ToJSON() map[string]bool {
|
||||||
return map[string]bool{
|
return map[string]bool{
|
||||||
"builtin": f&BUILTIN != 0,
|
"builtin": f&BUILTIN != 0,
|
||||||
"dynamic": f&DYNAMIC != 0,
|
"dynamic": f&DYNAMIC != 0,
|
||||||
"release": f&RELEASE != 0,
|
"release": f&RELEASE != 0,
|
||||||
"consumable": f&CONSUMABLE != 0,
|
"consumable": f&CONSUMABLE != 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResourceInfo struct {
|
type ResourceInfo struct {
|
||||||
ResName string
|
ResName string
|
||||||
Description string
|
Description string
|
||||||
ValueType ValueType
|
ValueType ValueType
|
||||||
OrderType OrderType
|
OrderType OrderType
|
||||||
Flag int
|
Flag int
|
||||||
Interval int
|
Interval int
|
||||||
}
|
}
|
||||||
|
|
||||||
// queues info query supported filter
|
// queues info query supported filter
|
||||||
var RESOURCE_DISTRIBUTION_SUPPORT_FILTERS = []string{
|
var RESOURCE_DISTRIBUTION_SUPPORT_FILTERS = []string{
|
||||||
"res_name",
|
"res_name",
|
||||||
"is_dynamic",
|
"is_dynamic",
|
||||||
"location",
|
"location",
|
||||||
}
|
}
|
||||||
|
|
||||||
var RESOURCE_DEFINITION_SUPPORT_FILTERS = []string{
|
var RESOURCE_DEFINITION_SUPPORT_FILTERS = []string{
|
||||||
"res_name",
|
"res_name",
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResourceDistributionInfo struct {
|
type ResourceDistributionInfo struct {
|
||||||
ResourceName string `json:"res_name"`
|
ResourceName string `json:"res_name"`
|
||||||
IsDynamic bool `json:"is_dynamic"`
|
IsDynamic bool `json:"is_dynamic"`
|
||||||
ValueType int `json:"value_type"`
|
ValueType int `json:"value_type"`
|
||||||
BooleanValue bool `json:"boolean_value"`
|
BooleanValue bool `json:"boolean_value"`
|
||||||
StringValue string `json:"string_value"`
|
StringValue string `json:"string_value"`
|
||||||
NumericValue float64 `json:"numeric_value"`
|
NumericValue float64 `json:"numeric_value"`
|
||||||
Location string `json:"location"`
|
Location string `json:"location"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResourceDefinitionInfo struct {
|
type ResourceDefinitionInfo struct {
|
||||||
ResourceName string `json:"res_name"`
|
ResourceName string `json:"res_name"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
ValueType int `json:"value_type"`
|
ValueType int `json:"value_type"`
|
||||||
OrderType int `json:"order_type"`
|
OrderType int `json:"order_type"`
|
||||||
Flag int `json:"flag"`
|
Flag int `json:"flag"`
|
||||||
Interval int `json:"interval"`
|
Interval int `json:"interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var RESOURCE_DISTRIBUTION_SUPPORT_SORT = []string{
|
var RESOURCE_DISTRIBUTION_SUPPORT_SORT = []string{
|
||||||
"res_name",
|
"res_name",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ func TestIntegration_ConcurrentResourceValuePushes(t *testing.T) {
|
||||||
ResourceName: "mem",
|
ResourceName: "mem",
|
||||||
Location: "node01",
|
Location: "node01",
|
||||||
NumericValue: float64(idx + 1),
|
NumericValue: float64(idx + 1),
|
||||||
ValueType: 1, // NUMERIC
|
ValueType: 1, // NUMERIC
|
||||||
IsDynamic: true,
|
IsDynamic: true,
|
||||||
})
|
})
|
||||||
count.Add(1)
|
count.Add(1)
|
||||||
|
|
@ -129,4 +129,4 @@ func TestIntegration_ConcurrentResourceValuePushes(t *testing.T) {
|
||||||
if ResourceLocations.Count() != 1 {
|
if ResourceLocations.Count() != 1 {
|
||||||
t.Errorf("ResourceLocations count = %d, want 1 (key exists exactly once)", ResourceLocations.Count())
|
t.Errorf("ResourceLocations count = %d, want 1 (key exists exactly once)", ResourceLocations.Count())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@ import "apiserver/models"
|
||||||
|
|
||||||
// Global store instances.
|
// Global store instances.
|
||||||
var (
|
var (
|
||||||
Jobs *DataStore[uint64, models.JobInfo]
|
Jobs *DataStore[uint64, models.JobInfo]
|
||||||
ArrayJobs *DataStore[uint64, models.ArrayJobInfo]
|
ArrayJobs *DataStore[uint64, models.ArrayJobInfo]
|
||||||
Queues *DataStore[string, models.QueueInfo]
|
Queues *DataStore[string, models.QueueInfo]
|
||||||
Hosts *DataStore[string, models.HostInfo]
|
Hosts *DataStore[string, models.HostInfo]
|
||||||
Resources *DataStore[string, models.ResourceDefinitionInfo]
|
Resources *DataStore[string, models.ResourceDefinitionInfo]
|
||||||
ResourceLocations *DataStore[string, models.ResourceDistributionInfo]
|
ResourceLocations *DataStore[string, models.ResourceDistributionInfo]
|
||||||
Clusters *DataStore[string, models.ClusterInfo]
|
Clusters *DataStore[string, models.ClusterInfo]
|
||||||
JobExecHosts *DataStore[int64, models.JobExecHosts]
|
JobExecHosts *DataStore[int64, models.JobExecHosts]
|
||||||
Roles *DataStore[string, RoleEntry]
|
Roles *DataStore[string, RoleEntry]
|
||||||
UserRoles *DataStore[string, []string] // user_name → role_names
|
UserRoles *DataStore[string, []string] // user_name → role_names
|
||||||
)
|
)
|
||||||
|
|
||||||
// RoleEntry holds a role's permissions.
|
// RoleEntry holds a role's permissions.
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,50 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"xcecli/common/request"
|
"xcecli/common/request"
|
||||||
"xcecli/config"
|
"xcecli/config"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewListCmd create the list command
|
// NewListCmd create the list command
|
||||||
func NewListCmd(configManager *config.ConfigManager) *cobra.Command {
|
func NewListCmd(configManager *config.ConfigManager) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "list",
|
Use: "list",
|
||||||
GroupID: "api",
|
GroupID: "api",
|
||||||
Short: "List the API Servers",
|
Short: "List the API Servers",
|
||||||
Long: "List all the configured API Servers and the default API Server",
|
Long: "List all the configured API Servers and the default API Server",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runList(configManager)
|
return runList(configManager)
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runList(cm *config.ConfigManager) error {
|
func runList(cm *config.ConfigManager) error {
|
||||||
cfg, err := cm.GetConfig()
|
cfg, err := cm.GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errMsg := request.ExtractErrorMessage(err)
|
errMsg := request.ExtractErrorMessage(err)
|
||||||
return fmt.Errorf("failed to get the config: [%s]", errMsg)
|
return fmt.Errorf("failed to get the config: [%s]", errMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// use tabwriter to format the output
|
// use tabwriter to format the output
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||||
fmt.Fprintln(w, "Default\tVersion\tURL")
|
fmt.Fprintln(w, "Default\tVersion\tURL")
|
||||||
|
|
||||||
for _, server := range cfg.APIServerInfo {
|
for _, server := range cfg.APIServerInfo {
|
||||||
isDefault := " "
|
isDefault := " "
|
||||||
if server.Token == "" {
|
if server.Token == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(w, "%s\t%s\n",
|
fmt.Fprintf(w, "%s\t%s\n",
|
||||||
isDefault,
|
isDefault,
|
||||||
server.URL)
|
server.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
return w.Flush()
|
return w.Flush()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,38 @@
|
||||||
package jobs
|
package jobs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"xcecli/config"
|
"xcecli/config"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewJobsCmd creates a jobs query command
|
// NewJobsCmd creates a jobs query command
|
||||||
func NewJobsCmd(configManager *config.ConfigManager) *cobra.Command {
|
func NewJobsCmd(configManager *config.ConfigManager) *cobra.Command {
|
||||||
|
|
||||||
// Create the parent jobs command
|
// Create the parent jobs command
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "jobs",
|
Use: "jobs",
|
||||||
GroupID: "query",
|
GroupID: "query",
|
||||||
Short: "Manage jobs",
|
Short: "Manage jobs",
|
||||||
Long: `Manage jobs in the system.
|
Long: `Manage jobs in the system.
|
||||||
Use 'xce jobs list' to query jobs information.
|
Use 'xce jobs list' to query jobs information.
|
||||||
Use 'xce jobs <action>' to submit/kill/stop/resume/checkpoint/restart jobs.`,
|
Use 'xce jobs <action>' to submit/kill/stop/resume/checkpoint/restart jobs.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Display help when no subcommand is specified
|
// Display help when no subcommand is specified
|
||||||
cmd.Help()
|
cmd.Help()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.AddCommand(NewListJobsCmd(configManager))
|
cmd.AddCommand(NewListJobsCmd(configManager))
|
||||||
// Add submit command to jobs command
|
// Add submit command to jobs command
|
||||||
cmd.AddCommand(NewSubmitJobsCmd(configManager))
|
cmd.AddCommand(NewSubmitJobsCmd(configManager))
|
||||||
// Add job control sub-commands to jobs command
|
// Add job control sub-commands to jobs command
|
||||||
cmd.AddCommand(NewKillJobsCmd(configManager))
|
cmd.AddCommand(NewKillJobsCmd(configManager))
|
||||||
cmd.AddCommand(NewStopJobsCmd(configManager))
|
cmd.AddCommand(NewStopJobsCmd(configManager))
|
||||||
cmd.AddCommand(NewResumeJobsCmd(configManager))
|
cmd.AddCommand(NewResumeJobsCmd(configManager))
|
||||||
cmd.AddCommand(NewCheckPointJobsCmd(configManager))
|
cmd.AddCommand(NewCheckPointJobsCmd(configManager))
|
||||||
cmd.AddCommand(NewRestartJobsCmd(configManager))
|
cmd.AddCommand(NewRestartJobsCmd(configManager))
|
||||||
// Add peek command to view job output
|
// Add peek command to view job output
|
||||||
cmd.AddCommand(NewPeekJobsCmd(configManager))
|
cmd.AddCommand(NewPeekJobsCmd(configManager))
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,111 +1,111 @@
|
||||||
/*
|
/*
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright © 2025 xce
|
Copyright © 2025 xce
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"xcecli/config"
|
"xcecli/config"
|
||||||
logger "xcecli/config"
|
logger "xcecli/config"
|
||||||
cmd "xcecli/router"
|
cmd "xcecli/router"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GitCommit and BuildTime are injected at link time via
|
// GitCommit and BuildTime are injected at link time via
|
||||||
// `-ldflags "-X main.GitCommit=... -X main.BuildTime=..."` (see
|
// `-ldflags "-X main.GitCommit=... -X main.BuildTime=..."` (see
|
||||||
// src/tools/go_build). The
|
// src/tools/go_build). The
|
||||||
// "unknown" defaults matter: a bare `go build`/`go run` that bypasses that
|
// "unknown" defaults matter: a bare `go build`/`go run` that bypasses that
|
||||||
// ldflags injection must still report "unknown" rather than an empty
|
// ldflags injection must still report "unknown" rather than an empty
|
||||||
// string, matching this feature's unknown-fallback requirement (see
|
// string, matching this feature's unknown-fallback requirement (see
|
||||||
// xce_version_field() in src/lib/utils.c for the equivalent C-side
|
// xce_version_field() in src/lib/utils.c for the equivalent C-side
|
||||||
// convention).
|
// convention).
|
||||||
//
|
//
|
||||||
// DirtyFingerprint is injected the same way (`-X main.DirtyFingerprint=...`,
|
// DirtyFingerprint is injected the same way (`-X main.DirtyFingerprint=...`,
|
||||||
// see src/tools/go_build task 4.1) but its default is a deliberately EMPTY
|
// see src/tools/go_build task 4.1) but its default is a deliberately EMPTY
|
||||||
// string, not "unknown" -- matching dirty_fingerprint's convention
|
// string, not "unknown" -- matching dirty_fingerprint's convention
|
||||||
// everywhere else in the dirty-content-fingerprint feature (empty means
|
// everywhere else in the dirty-content-fingerprint feature (empty means
|
||||||
// "no fingerprint available", distinct from GitCommit/BuildTime's
|
// "no fingerprint available", distinct from GitCommit/BuildTime's
|
||||||
// "unknown" sentinel for "not injected at all").
|
// "unknown" sentinel for "not injected at all").
|
||||||
var (
|
var (
|
||||||
GitCommit = "unknown"
|
GitCommit = "unknown"
|
||||||
BuildTime = "unknown"
|
BuildTime = "unknown"
|
||||||
DirtyFingerprint = ""
|
DirtyFingerprint = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
// composeVersionDisplay applies the dirty-content-fingerprint feature's
|
// composeVersionDisplay applies the dirty-content-fingerprint feature's
|
||||||
// strip-and-append rule to gitCommit: if dirtyFingerprint is non-empty, a
|
// strip-and-append rule to gitCommit: if dirtyFingerprint is non-empty, a
|
||||||
// trailing "-dirty" suffix on gitCommit is stripped (an anchored suffix
|
// trailing "-dirty" suffix on gitCommit is stripped (an anchored suffix
|
||||||
// check via strings.TrimSuffix, not a blind substring replace) and
|
// check via strings.TrimSuffix, not a blind substring replace) and
|
||||||
// "-<dirtyFingerprint>" is appended in its place; otherwise gitCommit is
|
// "-<dirtyFingerprint>" is appended in its place; otherwise gitCommit is
|
||||||
// returned exactly as-is (already correctly showing "-dirty" or not, per
|
// returned exactly as-is (already correctly showing "-dirty" or not, per
|
||||||
// the original build-time-versioning feature). Mirrors
|
// the original build-time-versioning feature). Mirrors
|
||||||
// xce_compose_version_ex() in src/lib/utils.c (task 3.1) and apiserver's
|
// xce_compose_version_ex() in src/lib/utils.c (task 3.1) and apiserver's
|
||||||
// own composeVersionDisplay (task 4.4), the equivalent implementations
|
// own composeVersionDisplay (task 4.4), the equivalent implementations
|
||||||
// already approved for the other version-displaying components.
|
// already approved for the other version-displaying components.
|
||||||
//
|
//
|
||||||
// xcecli has no startup log to protect (already established as out of
|
// xcecli has no startup log to protect (already established as out of
|
||||||
// scope by the original build-time-versioning feature, see that feature's
|
// scope by the original build-time-versioning feature, see that feature's
|
||||||
// own task 4.5 commit fb09afe), so this result feeds the ONLY consumption
|
// own task 4.5 commit fb09afe), so this result feeds the ONLY consumption
|
||||||
// point below: the version string passed into router.Execute(cm, version),
|
// point below: the version string passed into router.Execute(cm, version),
|
||||||
// which sets rootCmd.Version for Cobra's native --version/-v handling.
|
// which sets rootCmd.Version for Cobra's native --version/-v handling.
|
||||||
func composeVersionDisplay(gitCommit, dirtyFingerprint string) string {
|
func composeVersionDisplay(gitCommit, dirtyFingerprint string) string {
|
||||||
if dirtyFingerprint == "" {
|
if dirtyFingerprint == "" {
|
||||||
return gitCommit
|
return gitCommit
|
||||||
}
|
}
|
||||||
return strings.TrimSuffix(gitCommit, "-dirty") + "-" + dirtyFingerprint
|
return strings.TrimSuffix(gitCommit, "-dirty") + "-" + dirtyFingerprint
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
// init logger
|
// init logger
|
||||||
if err := logger.InitLogger(); err != nil {
|
if err := logger.InitLogger(); err != nil {
|
||||||
fmt.Println(strings.ToLower(err.Error()))
|
fmt.Println(strings.ToLower(err.Error()))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
logger.Info("********** Initialize Logger on client side done!")
|
logger.Info("********** Initialize Logger on client side done!")
|
||||||
|
|
||||||
// initialize the config manager
|
// initialize the config manager
|
||||||
configManager, err := config.NewConfigManager()
|
configManager, err := config.NewConfigManager()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("failed to initialize the config manager", zap.Error(err))
|
fmt.Println("failed to initialize the config manager", zap.Error(err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure the config manager is initialized correctly
|
// ensure the config manager is initialized correctly
|
||||||
if configManager == nil {
|
if configManager == nil {
|
||||||
fmt.Println("failed to initialize the config manager")
|
fmt.Println("failed to initialize the config manager")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute the command
|
// execute the command
|
||||||
version := fmt.Sprintf("%s built %s", composeVersionDisplay(GitCommit, DirtyFingerprint), BuildTime)
|
version := fmt.Sprintf("%s built %s", composeVersionDisplay(GitCommit, DirtyFingerprint), BuildTime)
|
||||||
if err := cmd.Execute(configManager, version); err != nil {
|
if err := cmd.Execute(configManager, version); err != nil {
|
||||||
fmt.Println(strings.ToLower(err.Error()))
|
fmt.Println(strings.ToLower(err.Error()))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Use 'xce resources definition list' to query resources definition information.`,
|
||||||
distributionCmd := &cobra.Command{
|
distributionCmd := &cobra.Command{
|
||||||
Use: "distribution",
|
Use: "distribution",
|
||||||
Short: "Manage resource distribution",
|
Short: "Manage resource distribution",
|
||||||
Long: `Manage resource distribution information.
|
Long: `Manage resource distribution information.
|
||||||
Use 'xce resources distribution list' to query resources distribution information.`,
|
Use 'xce resources distribution list' to query resources distribution information.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Display help when no subcommand is specified
|
// Display help when no subcommand is specified
|
||||||
|
|
@ -39,7 +39,7 @@ Use 'xce resources distribution list' to query resources distribution informatio
|
||||||
definitionCmd := &cobra.Command{
|
definitionCmd := &cobra.Command{
|
||||||
Use: "definition",
|
Use: "definition",
|
||||||
Short: "Manage resource definition",
|
Short: "Manage resource definition",
|
||||||
Long: `Manage resource definition information.
|
Long: `Manage resource definition information.
|
||||||
Use 'xce resources definition list' to query resources definition information.`,
|
Use 'xce resources definition list' to query resources definition information.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Display help when no subcommand is specified
|
// Display help when no subcommand is specified
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,45 @@
|
||||||
package output
|
package output
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"xcecli/models"
|
"xcecli/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Output struct {
|
type Output struct {
|
||||||
fields string
|
fields string
|
||||||
formatJson bool
|
formatJson bool
|
||||||
noheader bool
|
noheader bool
|
||||||
verbose bool
|
verbose bool
|
||||||
wideFormat bool
|
wideFormat bool
|
||||||
jobStatusFilter []string
|
jobStatusFilter []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOutput(fields string, formatJson bool, noheader bool) *Output {
|
func NewOutput(fields string, formatJson bool, noheader bool) *Output {
|
||||||
return &Output{fields: fields, formatJson: formatJson, noheader: noheader}
|
return &Output{fields: fields, formatJson: formatJson, noheader: noheader}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Output) SetVerbose(verbose bool) {
|
func (o *Output) SetVerbose(verbose bool) {
|
||||||
o.verbose = verbose
|
o.verbose = verbose
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Output) SetNoHeader(noheader bool) {
|
func (o *Output) SetNoHeader(noheader bool) {
|
||||||
o.noheader = noheader
|
o.noheader = noheader
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Output) SetWideFormat(wideFormat bool) {
|
func (o *Output) SetWideFormat(wideFormat bool) {
|
||||||
o.wideFormat = wideFormat
|
o.wideFormat = wideFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Output) ClusterPrintData(cluster *models.ClusterInfo) {
|
func (o *Output) ClusterPrintData(cluster *models.ClusterInfo) {
|
||||||
printClustersVerboseOutput(cluster)
|
printClustersVerboseOutput(cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printClustersVerboseOutput(clusters *models.ClusterInfo) {
|
func printClustersVerboseOutput(clusters *models.ClusterInfo) {
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
|
||||||
defer w.Flush()
|
defer w.Flush()
|
||||||
fmt.Fprintf(w, "XCE Standard Cluster\t%s\t%s\n", clusters.Version, "Jul 08 2025")
|
fmt.Fprintf(w, "XCE Standard Cluster\t%s\t%s\n", clusters.Version, "Jul 08 2025")
|
||||||
fmt.Fprintf(w, "My cluster name: <%s>\n", clusters.ClusterName)
|
fmt.Fprintf(w, "My cluster name: <%s>\n", clusters.ClusterName)
|
||||||
fmt.Fprintf(w, "The cluster status: <%s>\n", clusters.Status)
|
fmt.Fprintf(w, "The cluster status: <%s>\n", clusters.Status)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,189 +1,189 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"go.uber.org/zap/zapcore"
|
"go.uber.org/zap/zapcore"
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Log *zap.Logger
|
Log *zap.Logger
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultLoggerConfigFile = "logger.yaml"
|
defaultLoggerConfigFile = "logger.yaml"
|
||||||
defaultLoggerOutputFile = "xcecli_out.log"
|
defaultLoggerOutputFile = "xcecli_out.log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoggerConfig struct {
|
type LoggerConfig struct {
|
||||||
Logging struct {
|
Logging struct {
|
||||||
Level string `yaml:"level"`
|
Level string `yaml:"level"`
|
||||||
Encoding string `yaml:"encoding"`
|
Encoding string `yaml:"encoding"`
|
||||||
OutputPath string `yaml:"outputPath"`
|
OutputPath string `yaml:"outputPath"`
|
||||||
File struct {
|
File struct {
|
||||||
MaxSize int `yaml:"maxSize"`
|
MaxSize int `yaml:"maxSize"`
|
||||||
MaxBackups int `yaml:"maxBackups"`
|
MaxBackups int `yaml:"maxBackups"`
|
||||||
MaxAge int `yaml:"maxAge"`
|
MaxAge int `yaml:"maxAge"`
|
||||||
Compress bool `yaml:"compress"`
|
Compress bool `yaml:"compress"`
|
||||||
} `yaml:"file"`
|
} `yaml:"file"`
|
||||||
EncoderConfig struct {
|
EncoderConfig struct {
|
||||||
MessageKey string `yaml:"messageKey"`
|
MessageKey string `yaml:"messageKey"`
|
||||||
LevelKey string `yaml:"levelKey"`
|
LevelKey string `yaml:"levelKey"`
|
||||||
TimeKey string `yaml:"timeKey"`
|
TimeKey string `yaml:"timeKey"`
|
||||||
NameKey string `yaml:"nameKey"`
|
NameKey string `yaml:"nameKey"`
|
||||||
CallerKey string `yaml:"callerKey"`
|
CallerKey string `yaml:"callerKey"`
|
||||||
FunctionKey string `yaml:"functionKey"`
|
FunctionKey string `yaml:"functionKey"`
|
||||||
StacktraceKey string `yaml:"stacktraceKey"`
|
StacktraceKey string `yaml:"stacktraceKey"`
|
||||||
EncodeTime string `yaml:"timeEncoder"`
|
EncodeTime string `yaml:"timeEncoder"`
|
||||||
EncodeLevel string `yaml:"levelEncoder"`
|
EncodeLevel string `yaml:"levelEncoder"`
|
||||||
} `yaml:"encoderConfig"`
|
} `yaml:"encoderConfig"`
|
||||||
} `yaml:"logging"`
|
} `yaml:"logging"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitLogger() error {
|
func InitLogger() error {
|
||||||
var err error
|
var err error
|
||||||
err = loadLoggerConfig()
|
err = loadLoggerConfig()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadLoggerConfig() error {
|
func loadLoggerConfig() error {
|
||||||
usr, err := user.Current()
|
usr, err := user.Current()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get the user info: [%v]", err)
|
return fmt.Errorf("failed to get the user info: [%v]", err)
|
||||||
}
|
}
|
||||||
// read logger configuration file
|
// read logger configuration file
|
||||||
configPath := filepath.Join(usr.HomeDir, ".xce")
|
configPath := filepath.Join(usr.HomeDir, ".xce")
|
||||||
|
|
||||||
var loggerConfig LoggerConfig
|
var loggerConfig LoggerConfig
|
||||||
v := viper.New()
|
v := viper.New()
|
||||||
|
|
||||||
v.SetDefault("logging.level", "info") // debug, info, warn, error, fatal
|
v.SetDefault("logging.level", "info") // debug, info, warn, error, fatal
|
||||||
v.SetDefault("logging.encoding", "console") // console, json
|
v.SetDefault("logging.encoding", "console") // console, json
|
||||||
v.SetDefault("logging.outputPath", defaultLoggerOutputFile) // xcecli_out.log
|
v.SetDefault("logging.outputPath", defaultLoggerOutputFile) // xcecli_out.log
|
||||||
v.SetDefault("logging.file.maxSize", 100) // 100MB
|
v.SetDefault("logging.file.maxSize", 100) // 100MB
|
||||||
v.SetDefault("logging.file.maxBackups", 10) // 10
|
v.SetDefault("logging.file.maxBackups", 10) // 10
|
||||||
v.SetDefault("logging.file.maxAge", 14) // 14 days
|
v.SetDefault("logging.file.maxAge", 14) // 14 days
|
||||||
v.SetDefault("logging.file.compress", true) // true
|
v.SetDefault("logging.file.compress", true) // true
|
||||||
v.SetDefault("logging.encoderConfig.messageKey", "message") // message
|
v.SetDefault("logging.encoderConfig.messageKey", "message") // message
|
||||||
v.SetDefault("logging.encoderConfig.levelKey", "level") // level
|
v.SetDefault("logging.encoderConfig.levelKey", "level") // level
|
||||||
v.SetDefault("logging.encoderConfig.timeKey", "timestamp") // timestamp
|
v.SetDefault("logging.encoderConfig.timeKey", "timestamp") // timestamp
|
||||||
v.SetDefault("logging.encoderConfig.nameKey", "logger") // logger
|
v.SetDefault("logging.encoderConfig.nameKey", "logger") // logger
|
||||||
v.SetDefault("logging.encoderConfig.callerKey", "caller") // caller
|
v.SetDefault("logging.encoderConfig.callerKey", "caller") // caller
|
||||||
v.SetDefault("logging.encoderConfig.functionKey", "func") // func
|
v.SetDefault("logging.encoderConfig.functionKey", "func") // func
|
||||||
v.SetDefault("logging.encoderConfig.stacktraceKey", "stacktrace") // stacktrace
|
v.SetDefault("logging.encoderConfig.stacktraceKey", "stacktrace") // stacktrace
|
||||||
v.SetDefault("logging.encoderConfig.timeEncoder", "ISO8601") // ISO8601
|
v.SetDefault("logging.encoderConfig.timeEncoder", "ISO8601") // ISO8601
|
||||||
v.SetDefault("logging.encoderConfig.levelEncoder", "capital") // capital
|
v.SetDefault("logging.encoderConfig.levelEncoder", "capital") // capital
|
||||||
v.SetConfigName(defaultLoggerConfigFile)
|
v.SetConfigName(defaultLoggerConfigFile)
|
||||||
v.SetConfigType("yaml")
|
v.SetConfigType("yaml")
|
||||||
v.AddConfigPath(configPath)
|
v.AddConfigPath(configPath)
|
||||||
// yamlContent := `# log level: debug, info, warn, error, fatal
|
// yamlContent := `# log level: debug, info, warn, error, fatal
|
||||||
// # debug: detailed log
|
// # debug: detailed log
|
||||||
// # info: normal log
|
// # info: normal log
|
||||||
// # warn: warning log
|
// # warn: warning log
|
||||||
// # error: error log
|
// # error: error log
|
||||||
// # fatal: fatal log` + v.GetString("logging.level")
|
// # fatal: fatal log` + v.GetString("logging.level")
|
||||||
|
|
||||||
err = v.ReadInConfig()
|
err = v.ReadInConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.MkdirAll(configPath, 0755)
|
os.MkdirAll(configPath, 0755)
|
||||||
|
|
||||||
if err = v.WriteConfigAs(filepath.Join(configPath, "logger.yaml")); err != nil {
|
if err = v.WriteConfigAs(filepath.Join(configPath, "logger.yaml")); err != nil {
|
||||||
fmt.Printf("failed to write default logger configuration file: [%v]", err)
|
fmt.Printf("failed to write default logger configuration file: [%v]", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = v.Unmarshal(&loggerConfig)
|
err = v.Unmarshal(&loggerConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to decode into struct: [%v]", err)
|
return fmt.Errorf("unable to decode into struct: [%v]", err)
|
||||||
}
|
}
|
||||||
// Handle both formats for OutputPath
|
// Handle both formats for OutputPath
|
||||||
if !filepath.IsAbs(loggerConfig.Logging.OutputPath) {
|
if !filepath.IsAbs(loggerConfig.Logging.OutputPath) {
|
||||||
if loggerConfig.Logging.OutputPath == "" {
|
if loggerConfig.Logging.OutputPath == "" {
|
||||||
loggerConfig.Logging.OutputPath = defaultLoggerOutputFile
|
loggerConfig.Logging.OutputPath = defaultLoggerOutputFile
|
||||||
}
|
}
|
||||||
// If OutputPath is relative, prepend the logs directory
|
// If OutputPath is relative, prepend the logs directory
|
||||||
loggerConfig.Logging.OutputPath = filepath.Join(configPath, "logs", loggerConfig.Logging.OutputPath)
|
loggerConfig.Logging.OutputPath = filepath.Join(configPath, "logs", loggerConfig.Logging.OutputPath)
|
||||||
}
|
}
|
||||||
logDir := filepath.Dir(loggerConfig.Logging.OutputPath) // Extract the directory
|
logDir := filepath.Dir(loggerConfig.Logging.OutputPath) // Extract the directory
|
||||||
// Create the directory if it does not exist
|
// Create the directory if it does not exist
|
||||||
if err = os.MkdirAll(logDir, 0755); err != nil {
|
if err = os.MkdirAll(logDir, 0755); err != nil {
|
||||||
return fmt.Errorf("failed to create client logs directory: %w", err)
|
return fmt.Errorf("failed to create client logs directory: %w", err)
|
||||||
}
|
}
|
||||||
Log, err = createLogger(loggerConfig)
|
Log, err = createLogger(loggerConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create client logger: %w", err)
|
return fmt.Errorf("failed to create client logger: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createLogger(loggerConfig LoggerConfig) (*zap.Logger, error) {
|
func createLogger(loggerConfig LoggerConfig) (*zap.Logger, error) {
|
||||||
configLevel, err := zapcore.ParseLevel(loggerConfig.Logging.Level)
|
configLevel, err := zapcore.ParseLevel(loggerConfig.Logging.Level)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// create log file and set the permission
|
// create log file and set the permission
|
||||||
file, err := os.OpenFile(loggerConfig.Logging.OutputPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
file, err := os.OpenFile(loggerConfig.Logging.OutputPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
file.Close()
|
file.Close()
|
||||||
|
|
||||||
// configure lumberjack for log rotation
|
// configure lumberjack for log rotation
|
||||||
logWriter := &lumberjack.Logger{
|
logWriter := &lumberjack.Logger{
|
||||||
Filename: loggerConfig.Logging.OutputPath,
|
Filename: loggerConfig.Logging.OutputPath,
|
||||||
MaxSize: loggerConfig.Logging.File.MaxSize,
|
MaxSize: loggerConfig.Logging.File.MaxSize,
|
||||||
MaxBackups: loggerConfig.Logging.File.MaxBackups,
|
MaxBackups: loggerConfig.Logging.File.MaxBackups,
|
||||||
MaxAge: loggerConfig.Logging.File.MaxAge,
|
MaxAge: loggerConfig.Logging.File.MaxAge,
|
||||||
Compress: loggerConfig.Logging.File.Compress,
|
Compress: loggerConfig.Logging.File.Compress,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create cores for different log levels
|
// Create cores for different log levels
|
||||||
core := zapcore.NewCore(
|
core := zapcore.NewCore(
|
||||||
zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
|
zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
|
||||||
MessageKey: loggerConfig.Logging.EncoderConfig.MessageKey,
|
MessageKey: loggerConfig.Logging.EncoderConfig.MessageKey,
|
||||||
LevelKey: loggerConfig.Logging.EncoderConfig.LevelKey,
|
LevelKey: loggerConfig.Logging.EncoderConfig.LevelKey,
|
||||||
TimeKey: loggerConfig.Logging.EncoderConfig.TimeKey,
|
TimeKey: loggerConfig.Logging.EncoderConfig.TimeKey,
|
||||||
NameKey: loggerConfig.Logging.EncoderConfig.NameKey,
|
NameKey: loggerConfig.Logging.EncoderConfig.NameKey,
|
||||||
CallerKey: loggerConfig.Logging.EncoderConfig.CallerKey,
|
CallerKey: loggerConfig.Logging.EncoderConfig.CallerKey,
|
||||||
StacktraceKey: "", // disable stacktrace
|
StacktraceKey: "", // disable stacktrace
|
||||||
EncodeTime: zapcore.ISO8601TimeEncoder,
|
EncodeTime: zapcore.ISO8601TimeEncoder,
|
||||||
EncodeLevel: zapcore.CapitalLevelEncoder,
|
EncodeLevel: zapcore.CapitalLevelEncoder,
|
||||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||||
ConsoleSeparator: " ",
|
ConsoleSeparator: " ",
|
||||||
}),
|
}),
|
||||||
zapcore.AddSync(logWriter),
|
zapcore.AddSync(logWriter),
|
||||||
configLevel,
|
configLevel,
|
||||||
)
|
)
|
||||||
logger := zap.New(core,
|
logger := zap.New(core,
|
||||||
zap.AddCaller(), // caller info
|
zap.AddCaller(), // caller info
|
||||||
zap.AddStacktrace(zap.ErrorLevel), // show error stacktrace
|
zap.AddStacktrace(zap.ErrorLevel), // show error stacktrace
|
||||||
zap.AddCallerSkip(1), // skip one layer of caller
|
zap.AddCallerSkip(1), // skip one layer of caller
|
||||||
)
|
)
|
||||||
return logger, nil
|
return logger, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Info(msg string, fields ...zap.Field) {
|
func Info(msg string, fields ...zap.Field) {
|
||||||
Log.WithOptions(zap.WithCaller(false)).Info(msg, fields...)
|
Log.WithOptions(zap.WithCaller(false)).Info(msg, fields...)
|
||||||
}
|
}
|
||||||
func Error(msg string, fields ...zap.Field) {
|
func Error(msg string, fields ...zap.Field) {
|
||||||
Log.WithOptions(zap.WithCaller(false)).Error(msg, fields...)
|
Log.WithOptions(zap.WithCaller(false)).Error(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Warn(msg string, fields ...zap.Field) {
|
func Warn(msg string, fields ...zap.Field) {
|
||||||
Log.WithOptions(zap.WithCaller(false)).Warn(msg, fields...)
|
Log.WithOptions(zap.WithCaller(false)).Warn(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Debug(msg string, fields ...zap.Field) {
|
func Debug(msg string, fields ...zap.Field) {
|
||||||
Log.WithOptions(zap.WithCaller(true)).Debug(msg, fields...)
|
Log.WithOptions(zap.WithCaller(true)).Debug(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fatal(msg string, fields ...zap.Field) {
|
func Fatal(msg string, fields ...zap.Field) {
|
||||||
Log.WithOptions(zap.WithCaller(false)).Fatal(msg, fields...)
|
Log.WithOptions(zap.WithCaller(false)).Fatal(msg, fields...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,92 +1,92 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/xeipuuv/gojsonschema"
|
"github.com/xeipuuv/gojsonschema"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// validate the specified yaml file format whether is correct
|
// validate the specified yaml file format whether is correct
|
||||||
// return the content of the yaml file if the format is correct
|
// return the content of the yaml file if the format is correct
|
||||||
// return error if the format is incorrect
|
// return error if the format is incorrect
|
||||||
func ValidateYamlFormat(yamlFilePath string) ([]byte, error) {
|
func ValidateYamlFormat(yamlFilePath string) ([]byte, error) {
|
||||||
// find the file path
|
// find the file path
|
||||||
yamlFilePath, err := filepath.Abs(yamlFilePath)
|
yamlFilePath, err := filepath.Abs(yamlFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// get scheme file path, suppose schema file is in the same directory as yaml file
|
// get scheme file path, suppose schema file is in the same directory as yaml file
|
||||||
yamlFileRootPath := filepath.Dir(yamlFilePath)
|
yamlFileRootPath := filepath.Dir(yamlFilePath)
|
||||||
realFileName := filepath.Base(yamlFilePath)
|
realFileName := filepath.Base(yamlFilePath)
|
||||||
preRealFileName := realFileName[:len(realFileName)-5] + "_schema.json"
|
preRealFileName := realFileName[:len(realFileName)-5] + "_schema.json"
|
||||||
schemaFilePath := filepath.Join(yamlFileRootPath, "schema", preRealFileName)
|
schemaFilePath := filepath.Join(yamlFileRootPath, "schema", preRealFileName)
|
||||||
// checking if the schema file exists
|
// checking if the schema file exists
|
||||||
if _, err := os.Stat(schemaFilePath); os.IsNotExist(err) {
|
if _, err := os.Stat(schemaFilePath); os.IsNotExist(err) {
|
||||||
err = fmt.Errorf("schema file %s does not exist ", schemaFilePath)
|
err = fmt.Errorf("schema file %s does not exist ", schemaFilePath)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ValidateYAML(yamlFilePath, schemaFilePath)
|
data, err := ValidateYAML(yamlFilePath, schemaFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateYAML validates the YAML content against the provided JSON schema
|
// ValidateYAML validates the YAML content against the provided JSON schema
|
||||||
func ValidateYAML(yamlPath, schemaPath string) ([]byte, error) {
|
func ValidateYAML(yamlPath, schemaPath string) ([]byte, error) {
|
||||||
// schemaLoader is a absolute file path
|
// schemaLoader is a absolute file path
|
||||||
schemaLoader := gojsonschema.NewReferenceLoader("file:///" + filepath.ToSlash(schemaPath))
|
schemaLoader := gojsonschema.NewReferenceLoader("file:///" + filepath.ToSlash(schemaPath))
|
||||||
// get yaml file content by reading the file
|
// get yaml file content by reading the file
|
||||||
data, err := os.ReadFile(yamlPath)
|
data, err := os.ReadFile(yamlPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// get the yaml file into object
|
// get the yaml file into object
|
||||||
var raw interface{}
|
var raw interface{}
|
||||||
err = yaml.Unmarshal(data, &raw)
|
err = yaml.Unmarshal(data, &raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// transform into map[string]interface{}
|
// transform into map[string]interface{}
|
||||||
yamlContent := convertYAML(raw)
|
yamlContent := convertYAML(raw)
|
||||||
|
|
||||||
// create documentLoader
|
// create documentLoader
|
||||||
documentLoader := gojsonschema.NewGoLoader(yamlContent)
|
documentLoader := gojsonschema.NewGoLoader(yamlContent)
|
||||||
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
|
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.Valid() {
|
if !result.Valid() {
|
||||||
var errorMessages string
|
var errorMessages string
|
||||||
for _, desc := range result.Errors() {
|
for _, desc := range result.Errors() {
|
||||||
errorMessages += fmt.Sprintf("- %s\n", desc)
|
errorMessages += fmt.Sprintf("- %s\n", desc)
|
||||||
}
|
}
|
||||||
err = errors.New(errorMessages)
|
err = errors.New(errorMessages)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the yaml content
|
// return the yaml content
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertYAML recursively converts map[interface{}]interface{} to map[string]interface{}
|
// convertYAML recursively converts map[interface{}]interface{} to map[string]interface{}
|
||||||
func convertYAML(i interface{}) interface{} {
|
func convertYAML(i interface{}) interface{} {
|
||||||
switch x := i.(type) {
|
switch x := i.(type) {
|
||||||
case map[interface{}]interface{}:
|
case map[interface{}]interface{}:
|
||||||
m2 := make(map[string]interface{})
|
m2 := make(map[string]interface{})
|
||||||
for k, v := range x {
|
for k, v := range x {
|
||||||
m2[fmt.Sprintf("%v", k)] = convertYAML(v)
|
m2[fmt.Sprintf("%v", k)] = convertYAML(v)
|
||||||
}
|
}
|
||||||
return m2
|
return m2
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
for idx, v := range x {
|
for idx, v := range x {
|
||||||
x[idx] = convertYAML(v)
|
x[idx] = convertYAML(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
type ClusterResponse struct {
|
type ClusterResponse struct {
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
Data struct {
|
Data struct {
|
||||||
Count int `json:"count"`
|
Count int `json:"count"`
|
||||||
Rows []ClusterInfo `json:"rows"`
|
Rows []ClusterInfo `json:"rows"`
|
||||||
Page_token string `json:"page_token"`
|
Page_token string `json:"page_token"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClusterInfo struct {
|
type ClusterInfo struct {
|
||||||
ClusterName string `json:"cluster_name"`
|
ClusterName string `json:"cluster_name"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
ControllerName string `json:"controller_name"`
|
ControllerName string `json:"controller_name"`
|
||||||
Resources interface{} `json:"resources"`
|
Resources interface{} `json:"resources"`
|
||||||
HostTypes interface{} `json:"host_types"`
|
HostTypes interface{} `json:"host_types"`
|
||||||
HostModels interface{} `json:"host_models"`
|
HostModels interface{} `json:"host_models"`
|
||||||
ClusterAdmins interface{} `json:"cluster_admins"`
|
ClusterAdmins interface{} `json:"cluster_admins"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,172 +1,172 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
const (
|
const (
|
||||||
HEADER_HOST_NAME = "HOST_NAME"
|
HEADER_HOST_NAME = "HOST_NAME"
|
||||||
HEADER_HOST_STATUS = "STATUS"
|
HEADER_HOST_STATUS = "STATUS"
|
||||||
HEADER_HOST_NCPUS = "NCPUS"
|
HEADER_HOST_NCPUS = "NCPUS"
|
||||||
HEADER_HOST_MAX_SLOT = "MAX_SLOT"
|
HEADER_HOST_MAX_SLOT = "MAX_SLOT"
|
||||||
HEADER_HOST_NUM_RUN = "NUM_RUN"
|
HEADER_HOST_NUM_RUN = "NUM_RUN"
|
||||||
HEADER_HOST_NUM_SSUSP = "NUM_SSUSP"
|
HEADER_HOST_NUM_SSUSP = "NUM_SSUSP"
|
||||||
HEADER_HOST_NUM_USUSP = "NUM_USUSP"
|
HEADER_HOST_NUM_USUSP = "NUM_USUSP"
|
||||||
HEADER_HOST_HOST_TYPE = "HOST_TYPE"
|
HEADER_HOST_HOST_TYPE = "HOST_TYPE"
|
||||||
// host details info
|
// host details info
|
||||||
HEADER_HOST_CPUF = "CPUF"
|
HEADER_HOST_CPUF = "CPUF"
|
||||||
HEADER_HOST_JLU = "JL/U"
|
HEADER_HOST_JLU = "JL/U"
|
||||||
HEADER_HOST_MAX = "MAX"
|
HEADER_HOST_MAX = "MAX"
|
||||||
HEADER_HOST_NJOBS = "NJOBS"
|
HEADER_HOST_NJOBS = "NJOBS"
|
||||||
HEADER_HOST_RUN = "RUN"
|
HEADER_HOST_RUN = "RUN"
|
||||||
HEADER_HOST_SSUSP = "SSUSP"
|
HEADER_HOST_SSUSP = "SSUSP"
|
||||||
HEADER_HOST_USUSP = "USUSP"
|
HEADER_HOST_USUSP = "USUSP"
|
||||||
HEADER_HOST_RSV = "RSV"
|
HEADER_HOST_RSV = "RSV"
|
||||||
HEADER_HOST_DISPT_WINDOW = "DISPATCH_WINDOW"
|
HEADER_HOST_DISPT_WINDOW = "DISPATCH_WINDOW"
|
||||||
// second line
|
// second line
|
||||||
HEADER_HOST_R15S = "r15s"
|
HEADER_HOST_R15S = "r15s"
|
||||||
HEADER_HOST_R1M = "r1m"
|
HEADER_HOST_R1M = "r1m"
|
||||||
HEADER_HOST_R15M = "r15m"
|
HEADER_HOST_R15M = "r15m"
|
||||||
HEADER_HOST_UT = "ut"
|
HEADER_HOST_UT = "ut"
|
||||||
HEADER_HOST_PG = "pg"
|
HEADER_HOST_PG = "pg"
|
||||||
HEADER_HOST_IO = "io"
|
HEADER_HOST_IO = "io"
|
||||||
HEADER_HOST_LS = "ls"
|
HEADER_HOST_LS = "ls"
|
||||||
HEADER_HOST_IT = "it"
|
HEADER_HOST_IT = "it"
|
||||||
HEADER_HOST_TMP = "tmp"
|
HEADER_HOST_TMP = "tmp"
|
||||||
HEADER_HOST_SWP = "swp"
|
HEADER_HOST_SWP = "swp"
|
||||||
HEADER_HOST_MEM = "mem"
|
HEADER_HOST_MEM = "mem"
|
||||||
HEADER_HOST_SLOTS = "slots"
|
HEADER_HOST_SLOTS = "slots"
|
||||||
)
|
)
|
||||||
|
|
||||||
var HostDetailHeaders = []string{
|
var HostDetailHeaders = []string{
|
||||||
HEADER_HOST_STATUS,
|
HEADER_HOST_STATUS,
|
||||||
HEADER_HOST_CPUF,
|
HEADER_HOST_CPUF,
|
||||||
HEADER_HOST_JLU,
|
HEADER_HOST_JLU,
|
||||||
HEADER_HOST_MAX,
|
HEADER_HOST_MAX,
|
||||||
HEADER_HOST_NJOBS,
|
HEADER_HOST_NJOBS,
|
||||||
HEADER_HOST_RUN,
|
HEADER_HOST_RUN,
|
||||||
HEADER_HOST_SSUSP,
|
HEADER_HOST_SSUSP,
|
||||||
HEADER_HOST_USUSP,
|
HEADER_HOST_USUSP,
|
||||||
HEADER_HOST_RSV,
|
HEADER_HOST_RSV,
|
||||||
HEADER_HOST_DISPT_WINDOW,
|
HEADER_HOST_DISPT_WINDOW,
|
||||||
}
|
}
|
||||||
|
|
||||||
var HostLoadSchedulingHeaders = []string{
|
var HostLoadSchedulingHeaders = []string{
|
||||||
HEADER_HOST_R15S,
|
HEADER_HOST_R15S,
|
||||||
HEADER_HOST_R1M,
|
HEADER_HOST_R1M,
|
||||||
HEADER_HOST_R15M,
|
HEADER_HOST_R15M,
|
||||||
HEADER_HOST_UT,
|
HEADER_HOST_UT,
|
||||||
HEADER_HOST_PG,
|
HEADER_HOST_PG,
|
||||||
HEADER_HOST_IO,
|
HEADER_HOST_IO,
|
||||||
HEADER_HOST_LS,
|
HEADER_HOST_LS,
|
||||||
HEADER_HOST_IT,
|
HEADER_HOST_IT,
|
||||||
HEADER_HOST_TMP,
|
HEADER_HOST_TMP,
|
||||||
HEADER_HOST_SWP,
|
HEADER_HOST_SWP,
|
||||||
HEADER_HOST_MEM,
|
HEADER_HOST_MEM,
|
||||||
HEADER_HOST_SLOTS,
|
HEADER_HOST_SLOTS,
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostsResponse define the data structure in the host query response
|
// HostsResponse define the data structure in the host query response
|
||||||
type HostsResponse struct {
|
type HostsResponse struct {
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
Data struct {
|
Data struct {
|
||||||
Count int `json:"count"`
|
Count int `json:"count"`
|
||||||
Rows []XCEHost `json:"rows"`
|
Rows []XCEHost `json:"rows"`
|
||||||
Page_token string `json:"page_token"`
|
Page_token string `json:"page_token"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host define the data structure in the host info\
|
// Host define the data structure in the host info\
|
||||||
type XCEHost struct {
|
type XCEHost struct {
|
||||||
HostID int64 `json:"host_id"`
|
HostID int64 `json:"host_id"`
|
||||||
HostName string `json:"host_name"`
|
HostName string `json:"host_name"`
|
||||||
HostStatus string `json:"host_status"`
|
HostStatus string `json:"host_status"`
|
||||||
HostModel string `json:"host_model"`
|
HostModel string `json:"host_model"`
|
||||||
HostType string `json:"host_type"`
|
HostType string `json:"host_type"`
|
||||||
HostGroup string `json:"host_group"`
|
HostGroup string `json:"host_group"`
|
||||||
Flag int `json:"flag"`
|
Flag int `json:"flag"`
|
||||||
CPUFactor float64 `json:"cpu_factor"`
|
CPUFactor float64 `json:"cpu_factor"`
|
||||||
DisptWindow interface{} `json:"dispt_window"`
|
DisptWindow interface{} `json:"dispt_window"`
|
||||||
NumCPUs int `json:"num_cpus"`
|
NumCPUs int `json:"num_cpus"`
|
||||||
MaxSlot int `json:"max_slot"`
|
MaxSlot int `json:"max_slot"`
|
||||||
MaxMem int `json:"max_mem"`
|
MaxMem int `json:"max_mem"`
|
||||||
MaxSwap int `json:"max_swap"`
|
MaxSwap int `json:"max_swap"`
|
||||||
MaxTmp int `json:"max_tmp"`
|
MaxTmp int `json:"max_tmp"`
|
||||||
NumDisk int `json:"num_disk"`
|
NumDisk int `json:"num_disk"`
|
||||||
NumRun int `json:"num_run"`
|
NumRun int `json:"num_run"`
|
||||||
NumSSusp int `json:"num_ssusp"`
|
NumSSusp int `json:"num_ssusp"`
|
||||||
NumUSusp int `json:"num_ususp"`
|
NumUSusp int `json:"num_ususp"`
|
||||||
NumDone int `json:"num_done"`
|
NumDone int `json:"num_done"`
|
||||||
AffTopo interface{} `json:"aff_topo"` // JSONB
|
AffTopo interface{} `json:"aff_topo"` // JSONB
|
||||||
GPUTopo interface{} `json:"gpu_topo"` // JSONB
|
GPUTopo interface{} `json:"gpu_topo"` // JSONB
|
||||||
SchedStop SchedStop `json:"sched_stop"` // JSONB
|
SchedStop SchedStop `json:"sched_stop"` // JSONB
|
||||||
RealLoad interface{} `json:"real_load"`
|
RealLoad interface{} `json:"real_load"`
|
||||||
|
|
||||||
// ResourceValues carries this host's live per-resource wire values
|
// ResourceValues carries this host's live per-resource wire values
|
||||||
// (r15s/r1m/r15m/ut/pg/io/ls/it/tmp/swp/mem/slots, among others), the
|
// (r15s/r1m/r15m/ut/pg/io/ls/it/tmp/swp/mem/slots, among others), the
|
||||||
// same set the C scheduler's own "info worker" REPL command shows --
|
// same set the C scheduler's own "info worker" REPL command shows --
|
||||||
// populated by the apiserver from the worker's own resval pushes.
|
// populated by the apiserver from the worker's own resval pushes.
|
||||||
ResourceValues []ResourceDistributionInfo `json:"resource_values"`
|
ResourceValues []ResourceDistributionInfo `json:"resource_values"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResourceDistributionInfo mirrors apiserver/models.ResourceDistributionInfo's
|
// ResourceDistributionInfo mirrors apiserver/models.ResourceDistributionInfo's
|
||||||
// JSON shape -- one resource's current value for one host/worker.
|
// JSON shape -- one resource's current value for one host/worker.
|
||||||
type ResourceDistributionInfo struct {
|
type ResourceDistributionInfo struct {
|
||||||
ResourceName string `json:"res_name"`
|
ResourceName string `json:"res_name"`
|
||||||
IsDynamic bool `json:"is_dynamic"`
|
IsDynamic bool `json:"is_dynamic"`
|
||||||
ValueType int `json:"value_type"`
|
ValueType int `json:"value_type"`
|
||||||
BooleanValue bool `json:"boolean_value"`
|
BooleanValue bool `json:"boolean_value"`
|
||||||
StringValue string `json:"string_value"`
|
StringValue string `json:"string_value"`
|
||||||
NumericValue float64 `json:"numeric_value"`
|
NumericValue float64 `json:"numeric_value"`
|
||||||
Location string `json:"location"`
|
Location string `json:"location"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var HostFieldsMap = map[string]string{
|
var HostFieldsMap = map[string]string{
|
||||||
HEADER_HOST_NAME: "host_name",
|
HEADER_HOST_NAME: "host_name",
|
||||||
HEADER_HOST_STATUS: "host_status",
|
HEADER_HOST_STATUS: "host_status",
|
||||||
HEADER_HOST_NCPUS: "num_cores",
|
HEADER_HOST_NCPUS: "num_cores",
|
||||||
HEADER_HOST_MAX_SLOT: "max_slot",
|
HEADER_HOST_MAX_SLOT: "max_slot",
|
||||||
HEADER_HOST_NUM_RUN: "num_run",
|
HEADER_HOST_NUM_RUN: "num_run",
|
||||||
HEADER_HOST_NUM_SSUSP: "num_ssusp",
|
HEADER_HOST_NUM_SSUSP: "num_ssusp",
|
||||||
HEADER_HOST_NUM_USUSP: "num_ususp",
|
HEADER_HOST_NUM_USUSP: "num_ususp",
|
||||||
HEADER_HOST_HOST_TYPE: "host_type",
|
HEADER_HOST_HOST_TYPE: "host_type",
|
||||||
}
|
}
|
||||||
|
|
||||||
type SchedStop struct {
|
type SchedStop struct {
|
||||||
Ls string `json:"ls"` // Load Sharing
|
Ls string `json:"ls"` // Load Sharing
|
||||||
Pg string `json:"pg"` // Page
|
Pg string `json:"pg"` // Page
|
||||||
R1m string `json:"r1m"` // Recent 1 minute
|
R1m string `json:"r1m"` // Recent 1 minute
|
||||||
Tmp string `json:"tmp"` // Temporary
|
Tmp string `json:"tmp"` // Temporary
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostControlRequest struct {
|
type HostControlRequest struct {
|
||||||
ControlAction string `json:"action" binding:"required"` //control action
|
ControlAction string `json:"action" binding:"required"` //control action
|
||||||
Hostname []string `json:"host_name" binding:"required"` //host name
|
Hostname []string `json:"host_name" binding:"required"` //host name
|
||||||
Comment string `json:"comment"` //comment
|
Comment string `json:"comment"` //comment
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostControlResponse struct {
|
type HostControlResponse struct {
|
||||||
Data struct {
|
Data struct {
|
||||||
Accepted []*HostControlResponseItem `json:"accepted"`
|
Accepted []*HostControlResponseItem `json:"accepted"`
|
||||||
Failed []*HostControlResponseItem `json:"failed"`
|
Failed []*HostControlResponseItem `json:"failed"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostControlResponseItem struct {
|
type HostControlResponseItem struct {
|
||||||
HostName string `json:"host_name"`
|
HostName string `json:"host_name"`
|
||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *XCEHost) UnmarshalJSON(data []byte) error {
|
func (h *XCEHost) UnmarshalJSON(data []byte) error {
|
||||||
type Alias XCEHost
|
type Alias XCEHost
|
||||||
var a Alias
|
var a Alias
|
||||||
if err := UnmarshalOrderMapRow(data, &a); err != nil {
|
if err := UnmarshalOrderMapRow(data, &a); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*h = XCEHost(a)
|
*h = XCEHost(a)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResReqSelectRequest struct {
|
type ResReqSelectRequest struct {
|
||||||
Select string `json:"select"`
|
Select string `json:"select"`
|
||||||
Order string `json:"order,omitempty"`
|
Order string `json:"order,omitempty"`
|
||||||
Limit int `json:"limit,omitempty"`
|
Limit int `json:"limit,omitempty"`
|
||||||
PageToken string `json:"page_token,omitempty"`
|
PageToken string `json:"page_token,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,6 @@ var JobLoadSchedulingHeaders = []string{
|
||||||
HEADER_JOB_MEM,
|
HEADER_JOB_MEM,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// for array jobs
|
// for array jobs
|
||||||
const (
|
const (
|
||||||
HEADER_ARRAY_JOB_JOBID = "JOBID"
|
HEADER_ARRAY_JOB_JOBID = "JOBID"
|
||||||
|
|
@ -93,96 +91,96 @@ type Jsonb struct {
|
||||||
|
|
||||||
// Job define the data structure in the job info
|
// Job define the data structure in the job info
|
||||||
type QueryJob struct {
|
type QueryJob struct {
|
||||||
JobID int64 `json:"job_id"`
|
JobID int64 `json:"job_id"`
|
||||||
SubmitUser string `json:"submit_user"`
|
SubmitUser string `json:"submit_user"`
|
||||||
JobStatus string `json:"job_status"`
|
JobStatus string `json:"job_status"`
|
||||||
JobName string `json:"job_name"`
|
JobName string `json:"job_name"`
|
||||||
Command string `json:"command"`
|
Command string `json:"command"`
|
||||||
QueueName string `json:"queue_name"`
|
QueueName string `json:"queue_name"`
|
||||||
ProjectName string `json:"project_name"`
|
ProjectName string `json:"project_name"`
|
||||||
UserGroup string `json:"user_group"`
|
UserGroup string `json:"user_group"`
|
||||||
LicenseProject string `json:"license_project"`
|
LicenseProject string `json:"license_project"`
|
||||||
JobDescription string `json:"job_description"`
|
JobDescription string `json:"job_description"`
|
||||||
Resreq string `json:"resreq"`
|
Resreq string `json:"resreq"`
|
||||||
RsvID string `json:"rsv_id"`
|
RsvID string `json:"rsv_id"`
|
||||||
SLA string `json:"sla"`
|
SLA string `json:"sla"`
|
||||||
MaxNumProcessors int `json:"maxnum_processors"`
|
MaxNumProcessors int `json:"maxnum_processors"`
|
||||||
NumProcessors int `json:"num_processors"`
|
NumProcessors int `json:"num_processors"`
|
||||||
AskedHosts string `json:"asked_hosts"`
|
AskedHosts string `json:"asked_hosts"`
|
||||||
BeginTime string `json:"begin_time"`
|
BeginTime string `json:"begin_time"`
|
||||||
TermTime string `json:"term_time"`
|
TermTime string `json:"term_time"`
|
||||||
UserPriority int `json:"user_priority"`
|
UserPriority int `json:"user_priority"`
|
||||||
DependCond string `json:"depend_cond"`
|
DependCond string `json:"depend_cond"`
|
||||||
SubmitTime int64 `json:"submit_time"`
|
SubmitTime int64 `json:"submit_time"`
|
||||||
ReserveTime int64 `json:"reserve_time"`
|
ReserveTime int64 `json:"reserve_time"`
|
||||||
StartTime int64 `json:"start_time"`
|
StartTime int64 `json:"start_time"`
|
||||||
EndTime int64 `json:"end_time"`
|
EndTime int64 `json:"end_time"`
|
||||||
JobRusage string `json:"job_rusage"`
|
JobRusage string `json:"job_rusage"`
|
||||||
MaxMem float64 `json:"max_mem"`
|
MaxMem float64 `json:"max_mem"`
|
||||||
AvgMem float64 `json:"avg_mem"`
|
AvgMem float64 `json:"avg_mem"`
|
||||||
UsedMem float64 `json:"used_mem"`
|
UsedMem float64 `json:"used_mem"`
|
||||||
CPUTime int `json:"cpu_time"`
|
CPUTime int `json:"cpu_time"`
|
||||||
PeakCPUTime int `json:"peak_cpu_time"`
|
PeakCPUTime int `json:"peak_cpu_time"`
|
||||||
PeakCPUDuration float64 `json:"peak_cpu_duration"`
|
PeakCPUDuration float64 `json:"peak_cpu_duration"`
|
||||||
MemEfficiency float64 `json:"mem_efficiency"` // Memory efficiency in percentage
|
MemEfficiency float64 `json:"mem_efficiency"` // Memory efficiency in percentage
|
||||||
AvgCPUEfficiency float64 `json:"avg_cpu_efficiency"` // Average CPU efficiency in percentage
|
AvgCPUEfficiency float64 `json:"avg_cpu_efficiency"` // Average CPU efficiency in percentage
|
||||||
PeakCPUEfficiency float64 `json:"peak_cpu_efficiency"` // Peak CPU efficiency in percentage
|
PeakCPUEfficiency float64 `json:"peak_cpu_efficiency"` // Peak CPU efficiency in percentage
|
||||||
NumHosts int `json:"num_hosts"` // Number of hosts used by the job
|
NumHosts int `json:"num_hosts"` // Number of hosts used by the job
|
||||||
FirstHost string `json:"first_host"` // First host where the job ran
|
FirstHost string `json:"first_host"` // First host where the job ran
|
||||||
AllocSlot string `json:"alloc_slots"` // Allocated slot information
|
AllocSlot string `json:"alloc_slots"` // Allocated slot information
|
||||||
Duration int `json:"duration"`
|
Duration int `json:"duration"`
|
||||||
Umask int `json:"umask"`
|
Umask int `json:"umask"`
|
||||||
CWD string `json:"cwd"`
|
CWD string `json:"cwd"`
|
||||||
SubmitHomeDir string `json:"submit_home_dir"`
|
SubmitHomeDir string `json:"submit_home_dir"`
|
||||||
FromHost string `json:"from_host"`
|
FromHost string `json:"from_host"`
|
||||||
ExecHosts ExecHosts `json:"exec_hosts"`
|
ExecHosts ExecHosts `json:"exec_hosts"`
|
||||||
ExitStatus ExitStatusValue `json:"exit_status"`
|
ExitStatus ExitStatusValue `json:"exit_status"`
|
||||||
ExecUID int `json:"exec_uid"`
|
ExecUID int `json:"exec_uid"`
|
||||||
ExecHome string `json:"exec_home"`
|
ExecHome string `json:"exec_home"`
|
||||||
ExecCWD string `json:"exec_cwd"`
|
ExecCWD string `json:"exec_cwd"`
|
||||||
ExecUserName string `json:"exec_user_name"`
|
ExecUserName string `json:"exec_user_name"`
|
||||||
JobPriority int `json:"job_priority"`
|
JobPriority int `json:"job_priority"`
|
||||||
ChargedSAAP string `json:"charged_SAAP"`
|
ChargedSAAP string `json:"charged_SAAP"`
|
||||||
PreExecCmd string `json:"pre_exec_cmd"`
|
PreExecCmd string `json:"pre_exec_cmd"`
|
||||||
PostExecCmd string `json:"post_exec_cmd"`
|
PostExecCmd string `json:"post_exec_cmd"`
|
||||||
RequeueErrorValues string `json:"requeue_error_values"`
|
RequeueErrorValues string `json:"requeue_error_values"`
|
||||||
NumLicenses int `json:"num_licenses"`
|
NumLicenses int `json:"num_licenses"`
|
||||||
LicenseNames []string `json:"license_names"`
|
LicenseNames []string `json:"license_names"`
|
||||||
RunTime int `json:"run_time"`
|
RunTime int `json:"run_time"`
|
||||||
RunTimeEstimation int `json:"run_time_estimation"`
|
RunTimeEstimation int `json:"run_time_estimation"`
|
||||||
MigThreshold int `json:"mig_threshold"`
|
MigThreshold int `json:"mig_threshold"`
|
||||||
ChkpntPeriod int `json:"chkpnt_period"`
|
ChkpntPeriod int `json:"chkpnt_period"`
|
||||||
ChkpntDir string `json:"chkpnt_dir"`
|
ChkpntDir string `json:"chkpnt_dir"`
|
||||||
OutDir string `json:"out_dir"`
|
OutDir string `json:"out_dir"`
|
||||||
InFile string `json:"in_file"`
|
InFile string `json:"in_file"`
|
||||||
OutFile string `json:"out_file"`
|
OutFile string `json:"out_file"`
|
||||||
ErrFile string `json:"err_file"`
|
ErrFile string `json:"err_file"`
|
||||||
MailUser string `json:"mail_user"`
|
MailUser string `json:"mail_user"`
|
||||||
LoginShell string `json:"login_shell"`
|
LoginShell string `json:"login_shell"`
|
||||||
ExceptList string `json:"except_list"`
|
ExceptList string `json:"except_list"`
|
||||||
RLimits64 []int64 `json:"rlimits64"`
|
RLimits64 []int64 `json:"rlimits64"`
|
||||||
SubEnvVars string `json:"sub_env_vars"`
|
SubEnvVars string `json:"sub_env_vars"`
|
||||||
PendingReason string `json:"pending_reason"`
|
PendingReason string `json:"pending_reason"`
|
||||||
JobStartInfo string `json:"job_start_info"`
|
JobStartInfo string `json:"job_start_info"`
|
||||||
JobExecInfo string `json:"job_exec_info"`
|
JobExecInfo string `json:"job_exec_info"`
|
||||||
CoreLimit float64 `json:"core_limit"`
|
CoreLimit float64 `json:"core_limit"`
|
||||||
CPULimit string `json:"cpu_limit"`
|
CPULimit string `json:"cpu_limit"`
|
||||||
RunLimit string `json:"run_limit"`
|
RunLimit string `json:"run_limit"`
|
||||||
FileLimit float64 `json:"file_limit"`
|
FileLimit float64 `json:"file_limit"`
|
||||||
DataLimit float64 `json:"data_limit"`
|
DataLimit float64 `json:"data_limit"`
|
||||||
StackLimit float64 `json:"stack_limit"`
|
StackLimit float64 `json:"stack_limit"`
|
||||||
MemLimit float64 `json:"mem_limit"`
|
MemLimit float64 `json:"mem_limit"`
|
||||||
SwapLimit float64 `json:"swap_limit"`
|
SwapLimit float64 `json:"swap_limit"`
|
||||||
ProcessLimit float64 `json:"process_limit"`
|
ProcessLimit float64 `json:"process_limit"`
|
||||||
ThreadLimit float64 `json:"thread_limit"`
|
ThreadLimit float64 `json:"thread_limit"`
|
||||||
NumFiles int `json:"num_files"`
|
NumFiles int `json:"num_files"`
|
||||||
ArrayIdx int `json:"array_idx"` //
|
ArrayIdx int `json:"array_idx"` //
|
||||||
UniqueJobID int64 `json:"unique_job_id"` //
|
UniqueJobID int64 `json:"unique_job_id"` //
|
||||||
ExtendData JobExtendData `json:"extend_data"`
|
ExtendData JobExtendData `json:"extend_data"`
|
||||||
InteractiveJobURL string `json:"interactive_job_url"`
|
InteractiveJobURL string `json:"interactive_job_url"`
|
||||||
PGIDs IntSlice `json:"pgids"`
|
PGIDs IntSlice `json:"pgids"`
|
||||||
PID IntSlice `json:"pids"`
|
PID IntSlice `json:"pids"`
|
||||||
LaunchType string `json:"launch_type"`
|
LaunchType string `json:"launch_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var JobFieldsMap = map[string]string{
|
var JobFieldsMap = map[string]string{
|
||||||
|
|
|
||||||
|
|
@ -1,124 +1,124 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
const (
|
const (
|
||||||
HEADER_QUEUE_NAME = "QUEUE_NAME"
|
HEADER_QUEUE_NAME = "QUEUE_NAME"
|
||||||
HEADER_QUEUE_PRIORITY = "PRIORITY"
|
HEADER_QUEUE_PRIORITY = "PRIORITY"
|
||||||
HEADER_QUEUE_STATUS = "QUEUE_STATUS"
|
HEADER_QUEUE_STATUS = "QUEUE_STATUS"
|
||||||
HEADER_QUEUE_NUM_PEND = "NUM_PEND"
|
HEADER_QUEUE_NUM_PEND = "NUM_PEND"
|
||||||
HEADER_QUEUE_NUM_RUN = "NUM_RUN"
|
HEADER_QUEUE_NUM_RUN = "NUM_RUN"
|
||||||
HEADER_QUEUE_NUM_SSUSP = "NUM_SSUSP"
|
HEADER_QUEUE_NUM_SSUSP = "NUM_SSUSP"
|
||||||
HEADER_QUEUE_NUM_USUSP = "NUM_USUSP"
|
HEADER_QUEUE_NUM_USUSP = "NUM_USUSP"
|
||||||
HEADER_QUEUE_NUM_DONE = "NUM_DONE"
|
HEADER_QUEUE_NUM_DONE = "NUM_DONE"
|
||||||
// queue detail info
|
// queue detail info
|
||||||
HEADER_QUEUE_PRIO = "PRIO"
|
HEADER_QUEUE_PRIO = "PRIO"
|
||||||
HEADER_QUEUE_NICE = "NICE"
|
HEADER_QUEUE_NICE = "NICE"
|
||||||
HEADER_QUEUE_MAX = "MAX"
|
HEADER_QUEUE_MAX = "MAX"
|
||||||
HEADER_QUEUE_JLU = "JL/U"
|
HEADER_QUEUE_JLU = "JL/U"
|
||||||
HEADER_QUEUE_JLP = "JL/P"
|
HEADER_QUEUE_JLP = "JL/P"
|
||||||
HEADER_QUEUE_JLH = "JL/H"
|
HEADER_QUEUE_JLH = "JL/H"
|
||||||
HEADER_QUEUE_NJOBS = "NJOBS"
|
HEADER_QUEUE_NJOBS = "NJOBS"
|
||||||
HEADER_QUEUE_PEND = "PEND"
|
HEADER_QUEUE_PEND = "PEND"
|
||||||
HEADER_QUEUE_RUN = "RUN"
|
HEADER_QUEUE_RUN = "RUN"
|
||||||
HEADER_QUEUE_SSUSP = "SSUSP"
|
HEADER_QUEUE_SSUSP = "SSUSP"
|
||||||
HEADER_QUEUE_USUSP = "USUSP"
|
HEADER_QUEUE_USUSP = "USUSP"
|
||||||
HEADER_QUEUE_RSV = "RSV"
|
HEADER_QUEUE_RSV = "RSV"
|
||||||
// second line
|
// second line
|
||||||
HEADER_QUEUE_R15S = "r15s"
|
HEADER_QUEUE_R15S = "r15s"
|
||||||
HEADER_QUEUE_R1M = "r1m"
|
HEADER_QUEUE_R1M = "r1m"
|
||||||
HEADER_QUEUE_R15M = "r15m"
|
HEADER_QUEUE_R15M = "r15m"
|
||||||
HEADER_QUEUE_UT = "ut"
|
HEADER_QUEUE_UT = "ut"
|
||||||
HEADER_QUEUE_PG = "pg"
|
HEADER_QUEUE_PG = "pg"
|
||||||
HEADER_QUEUE_IO = "io"
|
HEADER_QUEUE_IO = "io"
|
||||||
HEADER_QUEUE_LS = "ls"
|
HEADER_QUEUE_LS = "ls"
|
||||||
HEADER_QUEUE_IT = "it"
|
HEADER_QUEUE_IT = "it"
|
||||||
HEADER_QUEUE_TMP = "tmp"
|
HEADER_QUEUE_TMP = "tmp"
|
||||||
HEADER_QUEUE_SWP = "swp"
|
HEADER_QUEUE_SWP = "swp"
|
||||||
HEADER_QUEUE_MEM = "mem"
|
HEADER_QUEUE_MEM = "mem"
|
||||||
)
|
)
|
||||||
|
|
||||||
var QueueDetailHeaders = []string{
|
var QueueDetailHeaders = []string{
|
||||||
HEADER_QUEUE_PRIO,
|
HEADER_QUEUE_PRIO,
|
||||||
HEADER_QUEUE_NICE,
|
HEADER_QUEUE_NICE,
|
||||||
HEADER_QUEUE_STATUS,
|
HEADER_QUEUE_STATUS,
|
||||||
HEADER_QUEUE_MAX,
|
HEADER_QUEUE_MAX,
|
||||||
HEADER_QUEUE_JLU,
|
HEADER_QUEUE_JLU,
|
||||||
HEADER_QUEUE_JLP,
|
HEADER_QUEUE_JLP,
|
||||||
HEADER_QUEUE_JLH,
|
HEADER_QUEUE_JLH,
|
||||||
HEADER_QUEUE_NJOBS,
|
HEADER_QUEUE_NJOBS,
|
||||||
HEADER_QUEUE_PEND,
|
HEADER_QUEUE_PEND,
|
||||||
HEADER_QUEUE_RUN,
|
HEADER_QUEUE_RUN,
|
||||||
HEADER_QUEUE_SSUSP,
|
HEADER_QUEUE_SSUSP,
|
||||||
HEADER_QUEUE_USUSP,
|
HEADER_QUEUE_USUSP,
|
||||||
HEADER_QUEUE_RSV,
|
HEADER_QUEUE_RSV,
|
||||||
}
|
}
|
||||||
|
|
||||||
var QueueLoadSchedulingHeaders = []string{
|
var QueueLoadSchedulingHeaders = []string{
|
||||||
HEADER_QUEUE_R15S,
|
HEADER_QUEUE_R15S,
|
||||||
HEADER_QUEUE_R1M,
|
HEADER_QUEUE_R1M,
|
||||||
HEADER_QUEUE_R15M,
|
HEADER_QUEUE_R15M,
|
||||||
HEADER_QUEUE_UT,
|
HEADER_QUEUE_UT,
|
||||||
HEADER_QUEUE_PG,
|
HEADER_QUEUE_PG,
|
||||||
HEADER_QUEUE_IO,
|
HEADER_QUEUE_IO,
|
||||||
HEADER_QUEUE_LS,
|
HEADER_QUEUE_LS,
|
||||||
HEADER_QUEUE_IT,
|
HEADER_QUEUE_IT,
|
||||||
HEADER_QUEUE_TMP,
|
HEADER_QUEUE_TMP,
|
||||||
HEADER_QUEUE_SWP,
|
HEADER_QUEUE_SWP,
|
||||||
HEADER_QUEUE_MEM,
|
HEADER_QUEUE_MEM,
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueuesResponse define the data structure in the queue query response
|
// QueuesResponse define the data structure in the queue query response
|
||||||
type QueuesResponse struct {
|
type QueuesResponse struct {
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
Data struct {
|
Data struct {
|
||||||
Count int `json:"count"`
|
Count int `json:"count"`
|
||||||
Rows []DBQueueInfo `json:"rows"`
|
Rows []DBQueueInfo `json:"rows"`
|
||||||
Page_token string `json:"page_token"`
|
Page_token string `json:"page_token"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var QueueFieldsMap = map[string]string{
|
var QueueFieldsMap = map[string]string{
|
||||||
HEADER_QUEUE_NAME: "queue_name",
|
HEADER_QUEUE_NAME: "queue_name",
|
||||||
HEADER_QUEUE_PRIORITY: "priority",
|
HEADER_QUEUE_PRIORITY: "priority",
|
||||||
HEADER_QUEUE_STATUS: "queue_status",
|
HEADER_QUEUE_STATUS: "queue_status",
|
||||||
HEADER_QUEUE_NUM_PEND: "num_pend",
|
HEADER_QUEUE_NUM_PEND: "num_pend",
|
||||||
HEADER_QUEUE_NUM_RUN: "num_run",
|
HEADER_QUEUE_NUM_RUN: "num_run",
|
||||||
HEADER_QUEUE_NUM_SSUSP: "num_ssusp",
|
HEADER_QUEUE_NUM_SSUSP: "num_ssusp",
|
||||||
HEADER_QUEUE_NUM_USUSP: "num_ususp",
|
HEADER_QUEUE_NUM_USUSP: "num_ususp",
|
||||||
HEADER_QUEUE_NUM_DONE: "num_done",
|
HEADER_QUEUE_NUM_DONE: "num_done",
|
||||||
}
|
}
|
||||||
|
|
||||||
// DBQueueInfo define the data structure in the queue info
|
// DBQueueInfo define the data structure in the queue info
|
||||||
type DBQueueInfo struct {
|
type DBQueueInfo struct {
|
||||||
QueueName string `json:"queue_name"`
|
QueueName string `json:"queue_name"`
|
||||||
QueueStatus string `json:"queue_status"`
|
QueueStatus string `json:"queue_status"`
|
||||||
Priority int `json:"priority"`
|
Priority int `json:"priority"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
NumPend int `json:"num_pend"`
|
NumPend int `json:"num_pend"`
|
||||||
NumRun int `json:"num_run"`
|
NumRun int `json:"num_run"`
|
||||||
NumSSusp int `json:"num_ssusp"`
|
NumSSusp int `json:"num_ssusp"`
|
||||||
NumUSusp int `json:"num_ususp"`
|
NumUSusp int `json:"num_ususp"`
|
||||||
NumDone int `json:"num_done"`
|
NumDone int `json:"num_done"`
|
||||||
FSInfo map[string]interface{} `json:"fs_info"` // JSONB
|
FSInfo map[string]interface{} `json:"fs_info"` // JSONB
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueueControlRequest struct {
|
type QueueControlRequest struct {
|
||||||
ControlAction string `json:"action" binding:"required"` //control action
|
ControlAction string `json:"action" binding:"required"` //control action
|
||||||
QueueName []string `json:"queue_name" binding:"required"` //queue name
|
QueueName []string `json:"queue_name" binding:"required"` //queue name
|
||||||
Comment string `json:"comment"` //comment
|
Comment string `json:"comment"` //comment
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueueControlResponse struct {
|
type QueueControlResponse struct {
|
||||||
Data struct {
|
Data struct {
|
||||||
Accepted []*QueueControlResponseItem `json:"accepted"`
|
Accepted []*QueueControlResponseItem `json:"accepted"`
|
||||||
Failed []*QueueControlResponseItem `json:"failed"`
|
Failed []*QueueControlResponseItem `json:"failed"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueueControlResponseItem struct {
|
type QueueControlResponseItem struct {
|
||||||
QueueName string `json:"queue_name"`
|
QueueName string `json:"queue_name"`
|
||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *DBQueueInfo) UnmarshalJSON(data []byte) error {
|
func (q *DBQueueInfo) UnmarshalJSON(data []byte) error {
|
||||||
type Alias DBQueueInfo
|
type Alias DBQueueInfo
|
||||||
|
|
|
||||||
|
|
@ -1,117 +1,117 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
apiserver "xcecli/cmd/auth"
|
apiserver "xcecli/cmd/auth"
|
||||||
"xcecli/cmd/clusters"
|
"xcecli/cmd/clusters"
|
||||||
"xcecli/cmd/hosts"
|
"xcecli/cmd/hosts"
|
||||||
"xcecli/cmd/jobs"
|
"xcecli/cmd/jobs"
|
||||||
"xcecli/cmd/permissions"
|
"xcecli/cmd/permissions"
|
||||||
"xcecli/cmd/queues"
|
"xcecli/cmd/queues"
|
||||||
"xcecli/cmd/resources"
|
"xcecli/cmd/resources"
|
||||||
"xcecli/cmd/roles"
|
"xcecli/cmd/roles"
|
||||||
"xcecli/cmd/users"
|
"xcecli/cmd/users"
|
||||||
"xcecli/common/request"
|
"xcecli/common/request"
|
||||||
"xcecli/config"
|
"xcecli/config"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rootCmd = &cobra.Command{
|
rootCmd = &cobra.Command{
|
||||||
Use: "xce",
|
Use: "xce",
|
||||||
Short: "XCE CLI tool for the API Server operations",
|
Short: "XCE CLI tool for the API Server operations",
|
||||||
}
|
}
|
||||||
configManager *config.ConfigManager
|
configManager *config.ConfigManager
|
||||||
)
|
)
|
||||||
|
|
||||||
// execute the root command
|
// execute the root command
|
||||||
func Execute(cm *config.ConfigManager, version string) error {
|
func Execute(cm *config.ConfigManager, version string) error {
|
||||||
if cm == nil {
|
if cm == nil {
|
||||||
return fmt.Errorf("the config manager is not initialized")
|
return fmt.Errorf("the config manager is not initialized")
|
||||||
}
|
}
|
||||||
configManager = cm
|
configManager = cm
|
||||||
rootCmd.Version = version
|
rootCmd.Version = version
|
||||||
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||||
rootCmd.SilenceErrors = true
|
rootCmd.SilenceErrors = true
|
||||||
rootCmd.SilenceUsage = true
|
rootCmd.SilenceUsage = true
|
||||||
|
|
||||||
// initialize the subcommands
|
// initialize the subcommands
|
||||||
initCommands()
|
initCommands()
|
||||||
|
|
||||||
return rootCmd.Execute()
|
return rootCmd.Execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
// withAuth wraps a command with authentication check
|
// withAuth wraps a command with authentication check
|
||||||
// This function creates a middleware that checks authentication before executing any command
|
// This function creates a middleware that checks authentication before executing any command
|
||||||
func withAuth(cmd *cobra.Command) *cobra.Command {
|
func withAuth(cmd *cobra.Command) *cobra.Command {
|
||||||
// Store original handlers
|
// Store original handlers
|
||||||
originalRunE := cmd.RunE
|
originalRunE := cmd.RunE
|
||||||
originalRun := cmd.Run
|
originalRun := cmd.Run
|
||||||
|
|
||||||
// Create new RunE that checks authentication first
|
// Create new RunE that checks authentication first
|
||||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
// Check authentication before executing the command
|
// Check authentication before executing the command
|
||||||
_, err := configManager.IsAuthenticated()
|
_, err := configManager.IsAuthenticated()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the original command logic
|
// Execute the original command logic
|
||||||
if originalRunE != nil {
|
if originalRunE != nil {
|
||||||
return originalRunE(cmd, args)
|
return originalRunE(cmd, args)
|
||||||
}
|
}
|
||||||
if originalRun != nil {
|
if originalRun != nil {
|
||||||
originalRun(cmd, args)
|
originalRun(cmd, args)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// addCommandWithAuth adds a command and all its subcommands with authentication check
|
// addCommandWithAuth adds a command and all its subcommands with authentication check
|
||||||
func addCommandWithAuth(parent *cobra.Command, cmd *cobra.Command) {
|
func addCommandWithAuth(parent *cobra.Command, cmd *cobra.Command) {
|
||||||
// Apply auth check to the command itself
|
// Apply auth check to the command itself
|
||||||
withAuth(cmd)
|
withAuth(cmd)
|
||||||
|
|
||||||
// Apply auth check to all subcommands recursively
|
// Apply auth check to all subcommands recursively
|
||||||
for _, subCmd := range cmd.Commands() {
|
for _, subCmd := range cmd.Commands() {
|
||||||
withAuth(subCmd)
|
withAuth(subCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
parent.AddCommand(cmd)
|
parent.AddCommand(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize all the subcommands
|
// initialize all the subcommands
|
||||||
func initCommands() {
|
func initCommands() {
|
||||||
cobra.EnableCommandSorting = false
|
cobra.EnableCommandSorting = false
|
||||||
rootCmd.AddGroup(
|
rootCmd.AddGroup(
|
||||||
&cobra.Group{
|
&cobra.Group{
|
||||||
ID: "api",
|
ID: "api",
|
||||||
Title: "API Server Operations",
|
Title: "API Server Operations",
|
||||||
},
|
},
|
||||||
&cobra.Group{
|
&cobra.Group{
|
||||||
ID: "query",
|
ID: "query",
|
||||||
Title: "Query Operations",
|
Title: "Query Operations",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add authentication commands (no auth required)
|
// Add authentication commands (no auth required)
|
||||||
rootCmd.AddCommand(apiserver.NewLogonCmd(configManager))
|
rootCmd.AddCommand(apiserver.NewLogonCmd(configManager))
|
||||||
rootCmd.AddCommand(apiserver.NewLogoutCmd(configManager))
|
rootCmd.AddCommand(apiserver.NewLogoutCmd(configManager))
|
||||||
|
|
||||||
// Add commands that require authentication
|
// Add commands that require authentication
|
||||||
// These commands will automatically check authentication before execution
|
// These commands will automatically check authentication before execution
|
||||||
addCommandWithAuth(rootCmd, apiserver.NewListCmd(configManager))
|
addCommandWithAuth(rootCmd, apiserver.NewListCmd(configManager))
|
||||||
addCommandWithAuth(rootCmd, permissions.NewPermsCmd(configManager))
|
addCommandWithAuth(rootCmd, permissions.NewPermsCmd(configManager))
|
||||||
addCommandWithAuth(rootCmd, roles.NewRolesCmd(configManager))
|
addCommandWithAuth(rootCmd, roles.NewRolesCmd(configManager))
|
||||||
addCommandWithAuth(rootCmd, users.NewUsersCmd(configManager))
|
addCommandWithAuth(rootCmd, users.NewUsersCmd(configManager))
|
||||||
addCommandWithAuth(rootCmd, jobs.NewJobsCmd(configManager))
|
addCommandWithAuth(rootCmd, jobs.NewJobsCmd(configManager))
|
||||||
addCommandWithAuth(rootCmd, hosts.NewHostsCmd(configManager))
|
addCommandWithAuth(rootCmd, hosts.NewHostsCmd(configManager))
|
||||||
addCommandWithAuth(rootCmd, queues.NewQueuesCmd(configManager))
|
addCommandWithAuth(rootCmd, queues.NewQueuesCmd(configManager))
|
||||||
addCommandWithAuth(rootCmd, clusters.NewClustersCmd(configManager))
|
addCommandWithAuth(rootCmd, clusters.NewClustersCmd(configManager))
|
||||||
addCommandWithAuth(rootCmd, resources.NewResourcesCmd(configManager))
|
addCommandWithAuth(rootCmd, resources.NewResourcesCmd(configManager))
|
||||||
rootCmd.SetFlagErrorFunc(request.FlagErrorHandler)
|
rootCmd.SetFlagErrorFunc(request.FlagErrorHandler)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue