Update Node table code. Add simple unit test

This commit is contained in:
2025-10-16 12:54:16 +02:00
parent 89055506d6
commit 40398497c2
13 changed files with 678 additions and 296 deletions

View File

@@ -4,7 +4,7 @@ scalar Any
scalar NullableFloat scalar NullableFloat
scalar MetricScope scalar MetricScope
scalar JobState scalar JobState
scalar NodeState scalar SchedulerState
scalar MonitoringState scalar MonitoringState
type Node { type Node {
@@ -12,8 +12,11 @@ type Node {
hostname: String! hostname: String!
cluster: String! cluster: String!
subCluster: String! subCluster: String!
runningJobs: Int! jobsRunning: Int!
nodeState: NodeState! cpusAllocated: Int
memoryAllocated: Int
gpusAllocated: Int
schedulerState: SchedulerState!
healthState: MonitoringState! healthState: MonitoringState!
metaData: Any metaData: Any
} }
@@ -399,7 +402,7 @@ input NodeFilter {
hostname: StringInput hostname: StringInput
cluster: StringInput cluster: StringInput
subcluster: StringInput subcluster: StringInput
nodeState: NodeState schedulerState: SchedulerState
healthState: MonitoringState healthState: MonitoringState
} }

View File

@@ -6,18 +6,11 @@
"user": "clustercockpit", "user": "clustercockpit",
"group": "clustercockpit", "group": "clustercockpit",
"validate": false, "validate": false,
"apiAllowedIPs": [ "apiAllowedIPs": ["*"],
"*"
],
"short-running-jobs-duration": 300, "short-running-jobs-duration": 300,
"resampling": { "resampling": {
"trigger": 30, "trigger": 30,
"resolutions": [ "resolutions": [600, 300, 120, 60]
600,
300,
120,
60
]
} }
}, },
"cron": { "cron": {
@@ -54,3 +47,4 @@
} }
] ]
} }

14
go.mod
View File

@@ -6,7 +6,7 @@ toolchain go1.24.1
require ( require (
github.com/99designs/gqlgen v0.17.78 github.com/99designs/gqlgen v0.17.78
github.com/ClusterCockpit/cc-lib v0.9.1 github.com/ClusterCockpit/cc-lib v0.10.0
github.com/Masterminds/squirrel v1.5.4 github.com/Masterminds/squirrel v1.5.4
github.com/coreos/go-oidc/v3 v3.12.0 github.com/coreos/go-oidc/v3 v3.12.0
github.com/expr-lang/expr v1.17.6 github.com/expr-lang/expr v1.17.6
@@ -24,7 +24,7 @@ require (
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/linkedin/goavro/v2 v2.14.0 github.com/linkedin/goavro/v2 v2.14.0
github.com/mattn/go-sqlite3 v1.14.24 github.com/mattn/go-sqlite3 v1.14.24
github.com/nats-io/nats.go v1.45.0 github.com/nats-io/nats.go v1.46.1
github.com/prometheus/client_golang v1.23.2 github.com/prometheus/client_golang v1.23.2
github.com/prometheus/common v0.66.1 github.com/prometheus/common v0.66.1
github.com/qustavo/sqlhooks/v2 v2.1.0 github.com/qustavo/sqlhooks/v2 v2.1.0
@@ -32,7 +32,7 @@ require (
github.com/swaggo/http-swagger v1.3.4 github.com/swaggo/http-swagger v1.3.4
github.com/swaggo/swag v1.16.6 github.com/swaggo/swag v1.16.6
github.com/vektah/gqlparser/v2 v2.5.30 github.com/vektah/gqlparser/v2 v2.5.30
golang.org/x/crypto v0.41.0 golang.org/x/crypto v0.42.0
golang.org/x/oauth2 v0.30.0 golang.org/x/oauth2 v0.30.0
golang.org/x/time v0.13.0 golang.org/x/time v0.13.0
) )
@@ -86,12 +86,12 @@ require (
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/mod v0.26.0 // indirect golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.43.0 // indirect golang.org/x/net v0.43.0 // indirect
golang.org/x/sync v0.16.0 // indirect golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.28.0 // indirect golang.org/x/text v0.29.0 // indirect
golang.org/x/tools v0.35.0 // indirect golang.org/x/tools v0.36.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect google.golang.org/protobuf v1.36.8 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect

28
go.sum
View File

@@ -6,8 +6,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/ClusterCockpit/cc-lib v0.9.1 h1:pcUbpcbD1o4u7gILiBFVnO9DyQpji/Lgq+pIQ/CwxQo= github.com/ClusterCockpit/cc-lib v0.10.0 h1:Pa8mqVciCOipzXTO18ZL8vwMi2JJh/ZjQbCWXZl2R78=
github.com/ClusterCockpit/cc-lib v0.9.1/go.mod h1:RRud94Y5qXAvosww0LxbdBFKXndVN4FnwgS1PxVTKbc= github.com/ClusterCockpit/cc-lib v0.10.0/go.mod h1:nvTZuxFCTwlos8I1rL5O1RPab7vRtkU8E/PGiaF6pQA=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
@@ -207,8 +207,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/nats.go v1.45.0 h1:/wGPbnYXDM0pLKFjZTX+2JOw9TQPoIgTFrUaH97giwA= github.com/nats-io/nats.go v1.46.1 h1:bqQ2ZcxVd2lpYI97xYASeRTY3I5boe/IVmuUDPitHfo=
github.com/nats-io/nats.go v1.45.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g= github.com/nats-io/nats.go v1.46.1/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0= github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE= github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
@@ -295,8 +295,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -304,8 +304,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -328,8 +328,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -361,8 +361,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -371,8 +371,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=

View File

@@ -80,7 +80,8 @@ models:
Tag: { model: "github.com/ClusterCockpit/cc-lib/schema.Tag" } Tag: { model: "github.com/ClusterCockpit/cc-lib/schema.Tag" }
Resource: { model: "github.com/ClusterCockpit/cc-lib/schema.Resource" } Resource: { model: "github.com/ClusterCockpit/cc-lib/schema.Resource" }
JobState: { model: "github.com/ClusterCockpit/cc-lib/schema.JobState" } JobState: { model: "github.com/ClusterCockpit/cc-lib/schema.JobState" }
MonitoringState: Node: { model: "github.com/ClusterCockpit/cc-lib/schema.Node" }
SchedulerState:
{ model: "github.com/ClusterCockpit/cc-lib/schema.SchedulerState" } { model: "github.com/ClusterCockpit/cc-lib/schema.SchedulerState" }
HealthState: HealthState:
{ model: "github.com/ClusterCockpit/cc-lib/schema.MonitoringState" } { model: "github.com/ClusterCockpit/cc-lib/schema.MonitoringState" }

View File

@@ -15,18 +15,9 @@ import (
"github.com/ClusterCockpit/cc-lib/schema" "github.com/ClusterCockpit/cc-lib/schema"
) )
type Node struct {
Hostname string `json:"hostname"`
States []string `json:"states"`
CpusAllocated int `json:"cpusAllocated"`
MemoryAllocated int `json:"memoryAllocated"`
GpusAllocated int `json:"gpusAllocated"`
JobsRunning int `json:"jobsRunning"`
}
type UpdateNodeStatesRequest struct { type UpdateNodeStatesRequest struct {
Nodes []Node `json:"nodes"` Nodes []schema.NodePayload `json:"nodes"`
Cluster string `json:"cluster" example:"fritz"` Cluster string `json:"cluster" example:"fritz"`
} }
// this routine assumes that only one of them exists per node // this routine assumes that only one of them exists per node
@@ -75,7 +66,7 @@ func (api *RestApi) updateNodeStates(rw http.ResponseWriter, r *http.Request) {
for _, node := range req.Nodes { for _, node := range req.Nodes {
state := determineState(node.States) state := determineState(node.States)
nodeState := schema.NodeState{ nodeState := schema.NodeStateDB{
TimeStamp: time.Now().Unix(), NodeState: state, TimeStamp: time.Now().Unix(), NodeState: state,
CpusAllocated: node.CpusAllocated, CpusAllocated: node.CpusAllocated,
MemoryAllocated: node.MemoryAllocated, MemoryAllocated: node.MemoryAllocated,

View File

@@ -272,14 +272,17 @@ type ComplexityRoot struct {
} }
Node struct { Node struct {
Cluster func(childComplexity int) int Cluster func(childComplexity int) int
HealthState func(childComplexity int) int CpusAllocated func(childComplexity int) int
Hostname func(childComplexity int) int GpusAllocated func(childComplexity int) int
ID func(childComplexity int) int HealthState func(childComplexity int) int
MetaData func(childComplexity int) int Hostname func(childComplexity int) int
NodeState func(childComplexity int) int ID func(childComplexity int) int
RunningJobs func(childComplexity int) int JobsRunning func(childComplexity int) int
SubCluster func(childComplexity int) int MemoryAllocated func(childComplexity int) int
MetaData func(childComplexity int) int
SchedulerState func(childComplexity int) int
SubCluster func(childComplexity int) int
} }
NodeMetrics struct { NodeMetrics struct {
@@ -447,9 +450,11 @@ type MutationResolver interface {
UpdateConfiguration(ctx context.Context, name string, value string) (*string, error) UpdateConfiguration(ctx context.Context, name string, value string) (*string, error)
} }
type NodeResolver interface { type NodeResolver interface {
NodeState(ctx context.Context, obj *model.Node) (string, error) ID(ctx context.Context, obj *schema.Node) (string, error)
HealthState(ctx context.Context, obj *model.Node) (schema.SchedulerState, error)
MetaData(ctx context.Context, obj *model.Node) (any, error) SchedulerState(ctx context.Context, obj *schema.Node) (schema.SchedulerState, error)
HealthState(ctx context.Context, obj *schema.Node) (string, error)
MetaData(ctx context.Context, obj *schema.Node) (any, error)
} }
type QueryResolver interface { type QueryResolver interface {
Clusters(ctx context.Context) ([]*schema.Cluster, error) Clusters(ctx context.Context) ([]*schema.Cluster, error)
@@ -457,7 +462,7 @@ type QueryResolver interface {
GlobalMetrics(ctx context.Context) ([]*schema.GlobalMetricListItem, error) GlobalMetrics(ctx context.Context) ([]*schema.GlobalMetricListItem, error)
User(ctx context.Context, username string) (*model.User, error) User(ctx context.Context, username string) (*model.User, error)
AllocatedNodes(ctx context.Context, cluster string) ([]*model.Count, error) AllocatedNodes(ctx context.Context, cluster string) ([]*model.Count, error)
Node(ctx context.Context, id string) (*model.Node, error) Node(ctx context.Context, id string) (*schema.Node, error)
Nodes(ctx context.Context, filter []*model.NodeFilter, order *model.OrderByInput) (*model.NodeStateResultList, error) Nodes(ctx context.Context, filter []*model.NodeFilter, order *model.OrderByInput) (*model.NodeStateResultList, error)
NodeStates(ctx context.Context, filter []*model.NodeFilter) ([]*model.NodeStates, error) NodeStates(ctx context.Context, filter []*model.NodeFilter) ([]*model.NodeStates, error)
Job(ctx context.Context, id string) (*schema.Job, error) Job(ctx context.Context, id string) (*schema.Job, error)
@@ -1484,6 +1489,20 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Node.Cluster(childComplexity), true return e.complexity.Node.Cluster(childComplexity), true
case "Node.cpusAllocated":
if e.complexity.Node.CpusAllocated == nil {
break
}
return e.complexity.Node.CpusAllocated(childComplexity), true
case "Node.gpusAllocated":
if e.complexity.Node.GpusAllocated == nil {
break
}
return e.complexity.Node.GpusAllocated(childComplexity), true
case "Node.healthState": case "Node.healthState":
if e.complexity.Node.HealthState == nil { if e.complexity.Node.HealthState == nil {
break break
@@ -1505,6 +1524,20 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Node.ID(childComplexity), true return e.complexity.Node.ID(childComplexity), true
case "Node.jobsRunning":
if e.complexity.Node.JobsRunning == nil {
break
}
return e.complexity.Node.JobsRunning(childComplexity), true
case "Node.memoryAllocated":
if e.complexity.Node.MemoryAllocated == nil {
break
}
return e.complexity.Node.MemoryAllocated(childComplexity), true
case "Node.metaData": case "Node.metaData":
if e.complexity.Node.MetaData == nil { if e.complexity.Node.MetaData == nil {
break break
@@ -1512,19 +1545,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Node.MetaData(childComplexity), true return e.complexity.Node.MetaData(childComplexity), true
case "Node.nodeState": case "Node.schedulerState":
if e.complexity.Node.NodeState == nil { if e.complexity.Node.SchedulerState == nil {
break break
} }
return e.complexity.Node.NodeState(childComplexity), true return e.complexity.Node.SchedulerState(childComplexity), true
case "Node.runningJobs":
if e.complexity.Node.RunningJobs == nil {
break
}
return e.complexity.Node.RunningJobs(childComplexity), true
case "Node.subCluster": case "Node.subCluster":
if e.complexity.Node.SubCluster == nil { if e.complexity.Node.SubCluster == nil {
@@ -2342,7 +2368,7 @@ scalar Any
scalar NullableFloat scalar NullableFloat
scalar MetricScope scalar MetricScope
scalar JobState scalar JobState
scalar NodeState scalar SchedulerState
scalar MonitoringState scalar MonitoringState
type Node { type Node {
@@ -2350,8 +2376,11 @@ type Node {
hostname: String! hostname: String!
cluster: String! cluster: String!
subCluster: String! subCluster: String!
runningJobs: Int! jobsRunning: Int!
nodeState: NodeState! cpusAllocated: Int
memoryAllocated: Int
gpusAllocated: Int
schedulerState: SchedulerState!
healthState: MonitoringState! healthState: MonitoringState!
metaData: Any metaData: Any
} }
@@ -2737,7 +2766,7 @@ input NodeFilter {
hostname: StringInput hostname: StringInput
cluster: StringInput cluster: StringInput
subcluster: StringInput subcluster: StringInput
nodeState: NodeState schedulerState: SchedulerState
healthState: MonitoringState healthState: MonitoringState
} }
@@ -9679,7 +9708,7 @@ func (ec *executionContext) fieldContext_NamedStatsWithScope_stats(_ context.Con
return fc, nil return fc, nil
} }
func (ec *executionContext) _Node_id(ctx context.Context, field graphql.CollectedField, obj *model.Node) (ret graphql.Marshaler) { func (ec *executionContext) _Node_id(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_id(ctx, field) fc, err := ec.fieldContext_Node_id(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
@@ -9693,7 +9722,7 @@ func (ec *executionContext) _Node_id(ctx context.Context, field graphql.Collecte
}() }()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children ctx = rctx // use context from middleware stack in children
return obj.ID, nil return ec.resolvers.Node().ID(rctx, obj)
}) })
if err != nil { if err != nil {
ec.Error(ctx, err) ec.Error(ctx, err)
@@ -9705,17 +9734,17 @@ func (ec *executionContext) _Node_id(ctx context.Context, field graphql.Collecte
} }
return graphql.Null return graphql.Null
} }
res := resTmp.(int64) res := resTmp.(string)
fc.Result = res fc.Result = res
return ec.marshalNID2int64(ctx, field.Selections, res) return ec.marshalNID2string(ctx, field.Selections, res)
} }
func (ec *executionContext) fieldContext_Node_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { func (ec *executionContext) fieldContext_Node_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{ fc = &graphql.FieldContext{
Object: "Node", Object: "Node",
Field: field, Field: field,
IsMethod: false, IsMethod: true,
IsResolver: false, IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type ID does not have child fields") return nil, errors.New("field of type ID does not have child fields")
}, },
@@ -9723,7 +9752,7 @@ func (ec *executionContext) fieldContext_Node_id(_ context.Context, field graphq
return fc, nil return fc, nil
} }
func (ec *executionContext) _Node_hostname(ctx context.Context, field graphql.CollectedField, obj *model.Node) (ret graphql.Marshaler) { func (ec *executionContext) _Node_hostname(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_hostname(ctx, field) fc, err := ec.fieldContext_Node_hostname(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
@@ -9767,7 +9796,7 @@ func (ec *executionContext) fieldContext_Node_hostname(_ context.Context, field
return fc, nil return fc, nil
} }
func (ec *executionContext) _Node_cluster(ctx context.Context, field graphql.CollectedField, obj *model.Node) (ret graphql.Marshaler) { func (ec *executionContext) _Node_cluster(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_cluster(ctx, field) fc, err := ec.fieldContext_Node_cluster(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
@@ -9811,7 +9840,7 @@ func (ec *executionContext) fieldContext_Node_cluster(_ context.Context, field g
return fc, nil return fc, nil
} }
func (ec *executionContext) _Node_subCluster(ctx context.Context, field graphql.CollectedField, obj *model.Node) (ret graphql.Marshaler) { func (ec *executionContext) _Node_subCluster(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_subCluster(ctx, field) fc, err := ec.fieldContext_Node_subCluster(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
@@ -9855,8 +9884,8 @@ func (ec *executionContext) fieldContext_Node_subCluster(_ context.Context, fiel
return fc, nil return fc, nil
} }
func (ec *executionContext) _Node_runningJobs(ctx context.Context, field graphql.CollectedField, obj *model.Node) (ret graphql.Marshaler) { func (ec *executionContext) _Node_jobsRunning(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_runningJobs(ctx, field) fc, err := ec.fieldContext_Node_jobsRunning(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
} }
@@ -9869,7 +9898,7 @@ func (ec *executionContext) _Node_runningJobs(ctx context.Context, field graphql
}() }()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children ctx = rctx // use context from middleware stack in children
return obj.RunningJobs, nil return obj.JobsRunning, nil
}) })
if err != nil { if err != nil {
ec.Error(ctx, err) ec.Error(ctx, err)
@@ -9886,7 +9915,7 @@ func (ec *executionContext) _Node_runningJobs(ctx context.Context, field graphql
return ec.marshalNInt2int(ctx, field.Selections, res) return ec.marshalNInt2int(ctx, field.Selections, res)
} }
func (ec *executionContext) fieldContext_Node_runningJobs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { func (ec *executionContext) fieldContext_Node_jobsRunning(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{ fc = &graphql.FieldContext{
Object: "Node", Object: "Node",
Field: field, Field: field,
@@ -9899,8 +9928,8 @@ func (ec *executionContext) fieldContext_Node_runningJobs(_ context.Context, fie
return fc, nil return fc, nil
} }
func (ec *executionContext) _Node_nodeState(ctx context.Context, field graphql.CollectedField, obj *model.Node) (ret graphql.Marshaler) { func (ec *executionContext) _Node_cpusAllocated(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_nodeState(ctx, field) fc, err := ec.fieldContext_Node_cpusAllocated(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
} }
@@ -9913,7 +9942,130 @@ func (ec *executionContext) _Node_nodeState(ctx context.Context, field graphql.C
}() }()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children ctx = rctx // use context from middleware stack in children
return ec.resolvers.Node().NodeState(rctx, obj) return obj.CpusAllocated, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(int)
fc.Result = res
return ec.marshalOInt2int(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Node_cpusAllocated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Node",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Node_memoryAllocated(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_memoryAllocated(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return obj.MemoryAllocated, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(int)
fc.Result = res
return ec.marshalOInt2int(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Node_memoryAllocated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Node",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Node_gpusAllocated(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_gpusAllocated(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return obj.GpusAllocated, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(int)
fc.Result = res
return ec.marshalOInt2int(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Node_gpusAllocated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Node",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Node_schedulerState(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_schedulerState(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Node().SchedulerState(rctx, obj)
}) })
if err != nil { if err != nil {
ec.Error(ctx, err) ec.Error(ctx, err)
@@ -9925,25 +10077,25 @@ func (ec *executionContext) _Node_nodeState(ctx context.Context, field graphql.C
} }
return graphql.Null return graphql.Null
} }
res := resTmp.(string) res := resTmp.(schema.SchedulerState)
fc.Result = res fc.Result = res
return ec.marshalNNodeState2string(ctx, field.Selections, res) return ec.marshalNSchedulerState2githubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx, field.Selections, res)
} }
func (ec *executionContext) fieldContext_Node_nodeState(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { func (ec *executionContext) fieldContext_Node_schedulerState(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{ fc = &graphql.FieldContext{
Object: "Node", Object: "Node",
Field: field, Field: field,
IsMethod: true, IsMethod: true,
IsResolver: true, IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type NodeState does not have child fields") return nil, errors.New("field of type SchedulerState does not have child fields")
}, },
} }
return fc, nil return fc, nil
} }
func (ec *executionContext) _Node_healthState(ctx context.Context, field graphql.CollectedField, obj *model.Node) (ret graphql.Marshaler) { func (ec *executionContext) _Node_healthState(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_healthState(ctx, field) fc, err := ec.fieldContext_Node_healthState(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
@@ -9969,9 +10121,9 @@ func (ec *executionContext) _Node_healthState(ctx context.Context, field graphql
} }
return graphql.Null return graphql.Null
} }
res := resTmp.(schema.SchedulerState) res := resTmp.(string)
fc.Result = res fc.Result = res
return ec.marshalNMonitoringState2githubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx, field.Selections, res) return ec.marshalNMonitoringState2string(ctx, field.Selections, res)
} }
func (ec *executionContext) fieldContext_Node_healthState(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { func (ec *executionContext) fieldContext_Node_healthState(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -9987,7 +10139,7 @@ func (ec *executionContext) fieldContext_Node_healthState(_ context.Context, fie
return fc, nil return fc, nil
} }
func (ec *executionContext) _Node_metaData(ctx context.Context, field graphql.CollectedField, obj *model.Node) (ret graphql.Marshaler) { func (ec *executionContext) _Node_metaData(ctx context.Context, field graphql.CollectedField, obj *schema.Node) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Node_metaData(ctx, field) fc, err := ec.fieldContext_Node_metaData(ctx, field)
if err != nil { if err != nil {
return graphql.Null return graphql.Null
@@ -10194,9 +10346,9 @@ func (ec *executionContext) _NodeStateResultList_items(ctx context.Context, fiel
} }
return graphql.Null return graphql.Null
} }
res := resTmp.([]*model.Node) res := resTmp.([]*schema.Node)
fc.Result = res fc.Result = res
return ec.marshalNNode2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐNodeᚄ(ctx, field.Selections, res) return ec.marshalNNode2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐNodeᚄ(ctx, field.Selections, res)
} }
func (ec *executionContext) fieldContext_NodeStateResultList_items(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { func (ec *executionContext) fieldContext_NodeStateResultList_items(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -10215,10 +10367,16 @@ func (ec *executionContext) fieldContext_NodeStateResultList_items(_ context.Con
return ec.fieldContext_Node_cluster(ctx, field) return ec.fieldContext_Node_cluster(ctx, field)
case "subCluster": case "subCluster":
return ec.fieldContext_Node_subCluster(ctx, field) return ec.fieldContext_Node_subCluster(ctx, field)
case "runningJobs": case "jobsRunning":
return ec.fieldContext_Node_runningJobs(ctx, field) return ec.fieldContext_Node_jobsRunning(ctx, field)
case "nodeState": case "cpusAllocated":
return ec.fieldContext_Node_nodeState(ctx, field) return ec.fieldContext_Node_cpusAllocated(ctx, field)
case "memoryAllocated":
return ec.fieldContext_Node_memoryAllocated(ctx, field)
case "gpusAllocated":
return ec.fieldContext_Node_gpusAllocated(ctx, field)
case "schedulerState":
return ec.fieldContext_Node_schedulerState(ctx, field)
case "healthState": case "healthState":
return ec.fieldContext_Node_healthState(ctx, field) return ec.fieldContext_Node_healthState(ctx, field)
case "metaData": case "metaData":
@@ -10922,9 +11080,9 @@ func (ec *executionContext) _Query_node(ctx context.Context, field graphql.Colle
if resTmp == nil { if resTmp == nil {
return graphql.Null return graphql.Null
} }
res := resTmp.(*model.Node) res := resTmp.(*schema.Node)
fc.Result = res fc.Result = res
return ec.marshalONode2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐNode(ctx, field.Selections, res) return ec.marshalONode2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐNode(ctx, field.Selections, res)
} }
func (ec *executionContext) fieldContext_Query_node(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { func (ec *executionContext) fieldContext_Query_node(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -10943,10 +11101,16 @@ func (ec *executionContext) fieldContext_Query_node(ctx context.Context, field g
return ec.fieldContext_Node_cluster(ctx, field) return ec.fieldContext_Node_cluster(ctx, field)
case "subCluster": case "subCluster":
return ec.fieldContext_Node_subCluster(ctx, field) return ec.fieldContext_Node_subCluster(ctx, field)
case "runningJobs": case "jobsRunning":
return ec.fieldContext_Node_runningJobs(ctx, field) return ec.fieldContext_Node_jobsRunning(ctx, field)
case "nodeState": case "cpusAllocated":
return ec.fieldContext_Node_nodeState(ctx, field) return ec.fieldContext_Node_cpusAllocated(ctx, field)
case "memoryAllocated":
return ec.fieldContext_Node_memoryAllocated(ctx, field)
case "gpusAllocated":
return ec.fieldContext_Node_gpusAllocated(ctx, field)
case "schedulerState":
return ec.fieldContext_Node_schedulerState(ctx, field)
case "healthState": case "healthState":
return ec.fieldContext_Node_healthState(ctx, field) return ec.fieldContext_Node_healthState(ctx, field)
case "metaData": case "metaData":
@@ -16666,7 +16830,7 @@ func (ec *executionContext) unmarshalInputNodeFilter(ctx context.Context, obj an
asMap[k] = v asMap[k] = v
} }
fieldsInOrder := [...]string{"hostname", "cluster", "subcluster", "nodeState", "healthState"} fieldsInOrder := [...]string{"hostname", "cluster", "subcluster", "schedulerState", "healthState"}
for _, k := range fieldsInOrder { for _, k := range fieldsInOrder {
v, ok := asMap[k] v, ok := asMap[k]
if !ok { if !ok {
@@ -16694,16 +16858,16 @@ func (ec *executionContext) unmarshalInputNodeFilter(ctx context.Context, obj an
return it, err return it, err
} }
it.Subcluster = data it.Subcluster = data
case "nodeState": case "schedulerState":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nodeState")) ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("schedulerState"))
data, err := ec.unmarshalONodeState2ᚖstring(ctx, v) data, err := ec.unmarshalOSchedulerState2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx, v)
if err != nil { if err != nil {
return it, err return it, err
} }
it.NodeState = data it.SchedulerState = data
case "healthState": case "healthState":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("healthState")) ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("healthState"))
data, err := ec.unmarshalOMonitoringState2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx, v) data, err := ec.unmarshalOMonitoringState2ᚖstring(ctx, v)
if err != nil { if err != nil {
return it, err return it, err
} }
@@ -18725,7 +18889,7 @@ func (ec *executionContext) _NamedStatsWithScope(ctx context.Context, sel ast.Se
var nodeImplementors = []string{"Node"} var nodeImplementors = []string{"Node"}
func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj *model.Node) graphql.Marshaler { func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj *schema.Node) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, nodeImplementors) fields := graphql.CollectFields(ec.OperationContext, sel, nodeImplementors)
out := graphql.NewFieldSet(fields) out := graphql.NewFieldSet(fields)
@@ -18735,10 +18899,41 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj
case "__typename": case "__typename":
out.Values[i] = graphql.MarshalString("Node") out.Values[i] = graphql.MarshalString("Node")
case "id": case "id":
out.Values[i] = ec._Node_id(ctx, field, obj) field := field
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1) innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._Node_id(ctx, field, obj)
if res == graphql.Null {
atomic.AddUint32(&fs.Invalids, 1)
}
return res
} }
if field.Deferrable != nil {
dfs, ok := deferred[field.Deferrable.Label]
di := 0
if ok {
dfs.AddField(field)
di = len(dfs.Values) - 1
} else {
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
deferred[field.Deferrable.Label] = dfs
}
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
return innerFunc(ctx, dfs)
})
// don't run the out.Concurrently() call below
out.Values[i] = graphql.Null
continue
}
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "hostname": case "hostname":
out.Values[i] = ec._Node_hostname(ctx, field, obj) out.Values[i] = ec._Node_hostname(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
@@ -18754,12 +18949,18 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1) atomic.AddUint32(&out.Invalids, 1)
} }
case "runningJobs": case "jobsRunning":
out.Values[i] = ec._Node_runningJobs(ctx, field, obj) out.Values[i] = ec._Node_jobsRunning(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1) atomic.AddUint32(&out.Invalids, 1)
} }
case "nodeState": case "cpusAllocated":
out.Values[i] = ec._Node_cpusAllocated(ctx, field, obj)
case "memoryAllocated":
out.Values[i] = ec._Node_memoryAllocated(ctx, field, obj)
case "gpusAllocated":
out.Values[i] = ec._Node_gpusAllocated(ctx, field, obj)
case "schedulerState":
field := field field := field
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
@@ -18768,7 +18969,7 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj
ec.Error(ctx, ec.Recover(ctx, r)) ec.Error(ctx, ec.Recover(ctx, r))
} }
}() }()
res = ec._Node_nodeState(ctx, field, obj) res = ec._Node_schedulerState(ctx, field, obj)
if res == graphql.Null { if res == graphql.Null {
atomic.AddUint32(&fs.Invalids, 1) atomic.AddUint32(&fs.Invalids, 1)
} }
@@ -21622,15 +21823,14 @@ func (ec *executionContext) marshalNMetricValue2githubᚗcomᚋClusterCockpitᚋ
return ec._MetricValue(ctx, sel, &v) return ec._MetricValue(ctx, sel, &v)
} }
func (ec *executionContext) unmarshalNMonitoringState2githubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx context.Context, v any) (schema.SchedulerState, error) { func (ec *executionContext) unmarshalNMonitoringState2string(ctx context.Context, v any) (string, error) {
tmp, err := graphql.UnmarshalString(v) res, err := graphql.UnmarshalString(v)
res := schema.SchedulerState(tmp)
return res, graphql.ErrorOnPath(ctx, err) return res, graphql.ErrorOnPath(ctx, err)
} }
func (ec *executionContext) marshalNMonitoringState2githubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx context.Context, sel ast.SelectionSet, v schema.SchedulerState) graphql.Marshaler { func (ec *executionContext) marshalNMonitoringState2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {
_ = sel _ = sel
res := graphql.MarshalString(string(v)) res := graphql.MarshalString(v)
if res == graphql.Null { if res == graphql.Null {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow") ec.Errorf(ctx, "the requested element is null which the schema does not allow")
@@ -21747,7 +21947,7 @@ func (ec *executionContext) marshalNNamedStatsWithScope2ᚖgithubᚗcomᚋCluste
return ec._NamedStatsWithScope(ctx, sel, v) return ec._NamedStatsWithScope(ctx, sel, v)
} }
func (ec *executionContext) marshalNNode2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐNodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Node) graphql.Marshaler { func (ec *executionContext) marshalNNode2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐNodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*schema.Node) graphql.Marshaler {
ret := make(graphql.Array, len(v)) ret := make(graphql.Array, len(v))
var wg sync.WaitGroup var wg sync.WaitGroup
isLen1 := len(v) == 1 isLen1 := len(v) == 1
@@ -21771,7 +21971,7 @@ func (ec *executionContext) marshalNNode2ᚕᚖgithubᚗcomᚋClusterCockpitᚋc
if !isLen1 { if !isLen1 {
defer wg.Done() defer wg.Done()
} }
ret[i] = ec.marshalNNode2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐNode(ctx, sel, v[i]) ret[i] = ec.marshalNNode2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐNode(ctx, sel, v[i])
} }
if isLen1 { if isLen1 {
f(i) f(i)
@@ -21791,7 +21991,7 @@ func (ec *executionContext) marshalNNode2ᚕᚖgithubᚗcomᚋClusterCockpitᚋc
return ret return ret
} }
func (ec *executionContext) marshalNNode2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐNode(ctx context.Context, sel ast.SelectionSet, v *model.Node) graphql.Marshaler { func (ec *executionContext) marshalNNode2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐNode(ctx context.Context, sel ast.SelectionSet, v *schema.Node) graphql.Marshaler {
if v == nil { if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow") ec.Errorf(ctx, "the requested element is null which the schema does not allow")
@@ -21860,22 +22060,6 @@ func (ec *executionContext) marshalNNodeMetrics2ᚖgithubᚗcomᚋClusterCockpit
return ec._NodeMetrics(ctx, sel, v) return ec._NodeMetrics(ctx, sel, v)
} }
func (ec *executionContext) unmarshalNNodeState2string(ctx context.Context, v any) (string, error) {
res, err := graphql.UnmarshalString(v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNNodeState2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler {
_ = sel
res := graphql.MarshalString(v)
if res == graphql.Null {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
}
}
return res
}
func (ec *executionContext) marshalNNodeStateResultList2githubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐNodeStateResultList(ctx context.Context, sel ast.SelectionSet, v model.NodeStateResultList) graphql.Marshaler { func (ec *executionContext) marshalNNodeStateResultList2githubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐNodeStateResultList(ctx context.Context, sel ast.SelectionSet, v model.NodeStateResultList) graphql.Marshaler {
return ec._NodeStateResultList(ctx, sel, &v) return ec._NodeStateResultList(ctx, sel, &v)
} }
@@ -22052,6 +22236,23 @@ func (ec *executionContext) marshalNResource2ᚖgithubᚗcomᚋClusterCockpitᚋ
return ec._Resource(ctx, sel, v) return ec._Resource(ctx, sel, v)
} }
func (ec *executionContext) unmarshalNSchedulerState2githubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx context.Context, v any) (schema.SchedulerState, error) {
tmp, err := graphql.UnmarshalString(v)
res := schema.SchedulerState(tmp)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNSchedulerState2githubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx context.Context, sel ast.SelectionSet, v schema.SchedulerState) graphql.Marshaler {
_ = sel
res := graphql.MarshalString(string(v))
if res == graphql.Null {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
}
}
return res
}
func (ec *executionContext) marshalNScopedStats2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐScopedStatsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ScopedStats) graphql.Marshaler { func (ec *executionContext) marshalNScopedStats2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐScopedStatsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ScopedStats) graphql.Marshaler {
ret := make(graphql.Array, len(v)) ret := make(graphql.Array, len(v))
var wg sync.WaitGroup var wg sync.WaitGroup
@@ -22910,6 +23111,18 @@ func (ec *executionContext) marshalOID2ᚕstringᚄ(ctx context.Context, sel ast
return ret return ret
} }
func (ec *executionContext) unmarshalOInt2int(ctx context.Context, v any) (int, error) {
res, err := graphql.UnmarshalInt(v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalOInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler {
_ = sel
_ = ctx
res := graphql.MarshalInt(v)
return res
}
func (ec *executionContext) unmarshalOInt2ᚕintᚄ(ctx context.Context, v any) ([]int, error) { func (ec *executionContext) unmarshalOInt2ᚕintᚄ(ctx context.Context, v any) ([]int, error) {
if v == nil { if v == nil {
return nil, nil return nil, nil
@@ -23217,26 +23430,25 @@ func (ec *executionContext) marshalOMetricStatistics2githubᚗcomᚋClusterCockp
return ec._MetricStatistics(ctx, sel, &v) return ec._MetricStatistics(ctx, sel, &v)
} }
func (ec *executionContext) unmarshalOMonitoringState2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx context.Context, v any) (*schema.SchedulerState, error) { func (ec *executionContext) unmarshalOMonitoringState2ᚖstring(ctx context.Context, v any) (*string, error) {
if v == nil { if v == nil {
return nil, nil return nil, nil
} }
tmp, err := graphql.UnmarshalString(v) res, err := graphql.UnmarshalString(v)
res := schema.SchedulerState(tmp)
return &res, graphql.ErrorOnPath(ctx, err) return &res, graphql.ErrorOnPath(ctx, err)
} }
func (ec *executionContext) marshalOMonitoringState2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx context.Context, sel ast.SelectionSet, v *schema.SchedulerState) graphql.Marshaler { func (ec *executionContext) marshalOMonitoringState2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {
if v == nil { if v == nil {
return graphql.Null return graphql.Null
} }
_ = sel _ = sel
_ = ctx _ = ctx
res := graphql.MarshalString(string(*v)) res := graphql.MarshalString(*v)
return res return res
} }
func (ec *executionContext) marshalONode2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐNode(ctx context.Context, sel ast.SelectionSet, v *model.Node) graphql.Marshaler { func (ec *executionContext) marshalONode2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐNode(ctx context.Context, sel ast.SelectionSet, v *schema.Node) graphql.Marshaler {
if v == nil { if v == nil {
return graphql.Null return graphql.Null
} }
@@ -23261,24 +23473,6 @@ func (ec *executionContext) unmarshalONodeFilter2ᚕᚖgithubᚗcomᚋClusterCoc
return res, nil return res, nil
} }
func (ec *executionContext) unmarshalONodeState2ᚖstring(ctx context.Context, v any) (*string, error) {
if v == nil {
return nil, nil
}
res, err := graphql.UnmarshalString(v)
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalONodeState2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler {
if v == nil {
return graphql.Null
}
_ = sel
_ = ctx
res := graphql.MarshalString(*v)
return res
}
func (ec *executionContext) unmarshalOOrderByInput2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐOrderByInput(ctx context.Context, v any) (*model.OrderByInput, error) { func (ec *executionContext) unmarshalOOrderByInput2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐOrderByInput(ctx context.Context, v any) (*model.OrderByInput, error) {
if v == nil { if v == nil {
return nil, nil return nil, nil
@@ -23295,6 +23489,25 @@ func (ec *executionContext) unmarshalOPageRequest2ᚖgithubᚗcomᚋClusterCockp
return &res, graphql.ErrorOnPath(ctx, err) return &res, graphql.ErrorOnPath(ctx, err)
} }
func (ec *executionContext) unmarshalOSchedulerState2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx context.Context, v any) (*schema.SchedulerState, error) {
if v == nil {
return nil, nil
}
tmp, err := graphql.UnmarshalString(v)
res := schema.SchedulerState(tmp)
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalOSchedulerState2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSchedulerState(ctx context.Context, sel ast.SelectionSet, v *schema.SchedulerState) graphql.Marshaler {
if v == nil {
return graphql.Null
}
_ = sel
_ = ctx
res := graphql.MarshalString(string(*v))
return res
}
func (ec *executionContext) marshalOSeries2ᚕgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSeriesᚄ(ctx context.Context, sel ast.SelectionSet, v []schema.Series) graphql.Marshaler { func (ec *executionContext) marshalOSeries2ᚕgithubᚗcomᚋClusterCockpitᚋccᚑlibᚋschemaᚐSeriesᚄ(ctx context.Context, sel ast.SelectionSet, v []schema.Series) graphql.Marshaler {
if v == nil { if v == nil {
return graphql.Null return graphql.Null

View File

@@ -4,20 +4,3 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package model package model
import (
"github.com/ClusterCockpit/cc-lib/schema"
)
type Node struct {
ID int64
Hostname string `json:"hostname"`
Cluster string `json:"cluster"`
SubCluster string `json:"subCluster"`
RunningJobs int `json:"jobsRunning"`
CpusAllocated int `json:"cpusAllocated"`
MemoryAllocated int `json:"memoryAllocated"`
GpusAllocated int `json:"gpusAllocated"`
NodeState schema.NodeState `json:"nodeState"`
HealthState schema.MonitoringState `json:"healthState"`
}

View File

@@ -171,11 +171,11 @@ type NamedStatsWithScope struct {
} }
type NodeFilter struct { type NodeFilter struct {
Hostname *StringInput `json:"hostname,omitempty"` Hostname *StringInput `json:"hostname,omitempty"`
Cluster *StringInput `json:"cluster,omitempty"` Cluster *StringInput `json:"cluster,omitempty"`
Subcluster *StringInput `json:"subcluster,omitempty"` Subcluster *StringInput `json:"subcluster,omitempty"`
NodeState *string `json:"nodeState,omitempty"` SchedulerState *schema.SchedulerState `json:"schedulerState,omitempty"`
HealthState *schema.SchedulerState `json:"healthState,omitempty"` HealthState *string `json:"healthState,omitempty"`
} }
type NodeMetrics struct { type NodeMetrics struct {
@@ -185,8 +185,8 @@ type NodeMetrics struct {
} }
type NodeStateResultList struct { type NodeStateResultList struct {
Items []*Node `json:"items"` Items []*schema.Node `json:"items"`
Count *int `json:"count,omitempty"` Count *int `json:"count,omitempty"`
} }
type NodeStates struct { type NodeStates struct {

View File

@@ -305,18 +305,23 @@ func (r *mutationResolver) UpdateConfiguration(ctx context.Context, name string,
return nil, nil return nil, nil
} }
// NodeState is the resolver for the nodeState field. // ID is the resolver for the id field.
func (r *nodeResolver) NodeState(ctx context.Context, obj *model.Node) (string, error) { func (r *nodeResolver) ID(ctx context.Context, obj *schema.Node) (string, error) {
panic(fmt.Errorf("not implemented: NodeState - nodeState")) panic(fmt.Errorf("not implemented: ID - id"))
}
// SchedulerState is the resolver for the schedulerState field.
func (r *nodeResolver) SchedulerState(ctx context.Context, obj *schema.Node) (schema.SchedulerState, error) {
panic(fmt.Errorf("not implemented: SchedulerState - schedulerState"))
} }
// HealthState is the resolver for the healthState field. // HealthState is the resolver for the healthState field.
func (r *nodeResolver) HealthState(ctx context.Context, obj *model.Node) (schema.SchedulerState, error) { func (r *nodeResolver) HealthState(ctx context.Context, obj *schema.Node) (string, error) {
panic(fmt.Errorf("not implemented: HealthState - healthState")) panic(fmt.Errorf("not implemented: HealthState - healthState"))
} }
// MetaData is the resolver for the metaData field. // MetaData is the resolver for the metaData field.
func (r *nodeResolver) MetaData(ctx context.Context, obj *model.Node) (any, error) { func (r *nodeResolver) MetaData(ctx context.Context, obj *schema.Node) (any, error) {
panic(fmt.Errorf("not implemented: MetaData - metaData")) panic(fmt.Errorf("not implemented: MetaData - metaData"))
} }
@@ -360,7 +365,7 @@ func (r *queryResolver) AllocatedNodes(ctx context.Context, cluster string) ([]*
} }
// Node is the resolver for the node field. // Node is the resolver for the node field.
func (r *queryResolver) Node(ctx context.Context, id string) (*model.Node, error) { func (r *queryResolver) Node(ctx context.Context, id string) (*schema.Node, error) {
panic(fmt.Errorf("not implemented: Node - node")) panic(fmt.Errorf("not implemented: Node - node"))
} }
@@ -822,3 +827,15 @@ type mutationResolver struct{ *Resolver }
type nodeResolver struct{ *Resolver } type nodeResolver struct{ *Resolver }
type queryResolver struct{ *Resolver } type queryResolver struct{ *Resolver }
type subClusterResolver struct{ *Resolver } type subClusterResolver struct{ *Resolver }
// !!! WARNING !!!
// The code below was going to be deleted when updating resolvers. It has been copied here so you have
// one last chance to move it out of harms way if you want. There are two reasons this happens:
// - When renaming or deleting a resolver the old code will be put in here. You can safely delete
// it when you're done.
// - You have helper methods in this file. Move them out to keep these resolver files clean.
/*
func (r *nodeResolver) NodeState(ctx context.Context, obj *model.Node) (string, error) {
panic(fmt.Errorf("not implemented: NodeState - nodeState"))
}
*/

View File

@@ -2,6 +2,7 @@
// All rights reserved. This file is part of cc-backend. // All rights reserved. This file is part of cc-backend.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package repository package repository
import ( import (

View File

@@ -10,7 +10,6 @@ import (
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
"maps"
"sync" "sync"
"time" "time"
@@ -50,90 +49,91 @@ func GetNodeRepository() *NodeRepository {
return nodeRepoInstance return nodeRepoInstance
} }
func (r *NodeRepository) FetchMetadata(node *schema.Node) (map[string]string, error) { func (r *NodeRepository) FetchMetadata(hostname string, cluster string) (map[string]string, error) {
start := time.Now() start := time.Now()
cachekey := fmt.Sprintf("metadata:%d", node.ID)
if cached := r.cache.Get(cachekey, nil); cached != nil {
node.MetaData = cached.(map[string]string)
return node.MetaData, nil
}
if err := sq.Select("node.meta_data").From("node").Where("node.id = ?", node.ID). RawMetaData := make([]byte, 0)
RunWith(r.stmtCache).QueryRow().Scan(&node.RawMetaData); err != nil {
if err := sq.Select("node.meta_data").From("node").
Where("node.hostname = ?", hostname).
Where("node.cluster = ?", cluster).
RunWith(r.stmtCache).QueryRow().Scan(&RawMetaData); err != nil {
cclog.Warn("Error while scanning for node metadata") cclog.Warn("Error while scanning for node metadata")
return nil, err return nil, err
} }
if len(node.RawMetaData) == 0 { if len(RawMetaData) == 0 {
return nil, nil return nil, nil
} }
if err := json.Unmarshal(node.RawMetaData, &node.MetaData); err != nil { MetaData := make(map[string]string)
if err := json.Unmarshal(RawMetaData, &MetaData); err != nil {
cclog.Warn("Error while unmarshaling raw metadata json") cclog.Warn("Error while unmarshaling raw metadata json")
return nil, err return nil, err
} }
r.cache.Put(cachekey, node.MetaData, len(node.RawMetaData), 24*time.Hour)
cclog.Debugf("Timer FetchMetadata %s", time.Since(start)) cclog.Debugf("Timer FetchMetadata %s", time.Since(start))
return node.MetaData, nil return MetaData, nil
} }
func (r *NodeRepository) UpdateMetadata(node *schema.Node, key, val string) (err error) { //
cachekey := fmt.Sprintf("metadata:%d", node.ID) // func (r *NodeRepository) UpdateMetadata(node *schema.Node, key, val string) (err error) {
r.cache.Del(cachekey) // cachekey := fmt.Sprintf("metadata:%d", node.ID)
if node.MetaData == nil { // r.cache.Del(cachekey)
if _, err = r.FetchMetadata(node); err != nil { // if node.MetaData == nil {
cclog.Warnf("Error while fetching metadata for node, DB ID '%v'", node.ID) // if _, err = r.FetchMetadata(node); err != nil {
return err // cclog.Warnf("Error while fetching metadata for node, DB ID '%v'", node.ID)
} // return err
} // }
// }
//
// if node.MetaData != nil {
// cpy := make(map[string]string, len(node.MetaData)+1)
// maps.Copy(cpy, node.MetaData)
// cpy[key] = val
// node.MetaData = cpy
// } else {
// node.MetaData = map[string]string{key: val}
// }
//
// if node.RawMetaData, err = json.Marshal(node.MetaData); err != nil {
// cclog.Warnf("Error while marshaling metadata for node, DB ID '%v'", node.ID)
// return err
// }
//
// if _, err = sq.Update("node").
// Set("meta_data", node.RawMetaData).
// Where("node.id = ?", node.ID).
// RunWith(r.stmtCache).Exec(); err != nil {
// cclog.Warnf("Error while updating metadata for node, DB ID '%v'", node.ID)
// return err
// }
//
// r.cache.Put(cachekey, node.MetaData, len(node.RawMetaData), 24*time.Hour)
// return nil
// }
if node.MetaData != nil { func (r *NodeRepository) GetNode(hostname string, cluster string, withMeta bool) (*schema.Node, error) {
cpy := make(map[string]string, len(node.MetaData)+1)
maps.Copy(cpy, node.MetaData)
cpy[key] = val
node.MetaData = cpy
} else {
node.MetaData = map[string]string{key: val}
}
if node.RawMetaData, err = json.Marshal(node.MetaData); err != nil {
cclog.Warnf("Error while marshaling metadata for node, DB ID '%v'", node.ID)
return err
}
if _, err = sq.Update("node").
Set("meta_data", node.RawMetaData).
Where("node.id = ?", node.ID).
RunWith(r.stmtCache).Exec(); err != nil {
cclog.Warnf("Error while updating metadata for node, DB ID '%v'", node.ID)
return err
}
r.cache.Put(cachekey, node.MetaData, len(node.RawMetaData), 24*time.Hour)
return nil
}
func (r *NodeRepository) GetNode(id int64, withMeta bool) (*schema.Node, error) {
node := &schema.Node{} node := &schema.Node{}
// if err := sq.Select("id", "hostname", "cluster", "subcluster", "node_state", if err := sq.Select("node.hostname", "node.cluster", "node.subcluster", "node_state.node_state",
// "health_state").From("node"). "node_state.health_state", "MAX(node_state.time_stamp)").From("node_state").
// Where("node.id = ?", id).RunWith(r.DB). Join("node ON nodes_state.node_id = node.id").GroupBy("node_state.node_id").
// QueryRow().Scan(&node.ID, &node.Hostname, &node.Cluster, &node.SubCluster, &node.NodeState, Where("node.hostname = ?", hostname).Where("node.cluster = ?", cluster).RunWith(r.DB).
// &node.HealthState); err != nil { QueryRow().Scan(&node.Hostname, &node.Cluster, &node.SubCluster, &node.NodeState, &node.HealthState); err != nil {
// cclog.Warnf("Error while querying node '%v' from database", id) cclog.Warnf("Error while querying node '%s' from database: %v", hostname, err)
// return nil, err return nil, err
// } }
//
// if withMeta { if withMeta {
// var err error var err error
// var meta map[string]string var meta map[string]string
// if meta, err = r.FetchMetadata(node); err != nil { if meta, err = r.FetchMetadata(hostname, cluster); err != nil {
// cclog.Warnf("Error while fetching metadata for node '%v'", id) cclog.Warnf("Error while fetching metadata for node '%s'", hostname)
// return nil, err return nil, err
// } }
// node.MetaData = meta node.MetaData = meta
// } }
return node, nil return node, nil
} }
@@ -151,7 +151,7 @@ INSERT INTO node (hostname, cluster, subcluster)
// AddNode adds a Node to the node table. This can be triggered by a node collector registration or // AddNode adds a Node to the node table. This can be triggered by a node collector registration or
// from a nodestate update from the job scheduler. // from a nodestate update from the job scheduler.
func (r *NodeRepository) AddNode(node *schema.Node) (int64, error) { func (r *NodeRepository) AddNode(node *schema.NodeDB) (int64, error) {
var err error var err error
res, err := r.DB.NamedExec(NamedNodeInsert, node) res, err := r.DB.NamedExec(NamedNodeInsert, node)
@@ -168,30 +168,15 @@ func (r *NodeRepository) AddNode(node *schema.Node) (int64, error) {
return node.ID, nil return node.ID, nil
} }
func (r *NodeRepository) InsertNodeState(nodeState *schema.Node) error {
subcluster, err := archive.GetSubClusterByNode(nodeState.Cluster, nodeState.Hostname)
if err != nil {
cclog.Errorf("Error while getting subcluster for node '%s' in cluster '%s': %v", nodeState.Hostname, nodeState.Cluster, err)
return err
}
nodeState.SubCluster = subcluster
_, err = r.DB.NamedExec(NamedNodeInsert, nodeState)
if err != nil {
cclog.Errorf("Error while insert node '%v' to database", nodeState.Hostname)
return err
}
return nil
}
const NamedNodeStateInsert string = ` const NamedNodeStateInsert string = `
INSERT INTO node_state (time_stamp, node_state, health_state, cpus_allocated, INSERT INTO node_state (time_stamp, node_state, health_state, cpus_allocated,
memory_allocated, gpus_allocated, jobs_running, node_id) memory_allocated, gpus_allocated, jobs_running, node_id)
VALUES (:time_stamp, :node_state, :health_state, :cpus_allocated, :memory_allocated, :gpus_allocated, :jobs_running, :node_id);` VALUES (:time_stamp, :node_state, :health_state, :cpus_allocated, :memory_allocated, :gpus_allocated, :jobs_running, :node_id);`
func (r *NodeRepository) UpdateNodeState(hostname string, cluster string, nodeState *schema.NodeState) error { // TODO: Add real Monitoring Health State
// UpdateNodeState is called from the Node REST API to add a row in the node state table
func (r *NodeRepository) UpdateNodeState(hostname string, cluster string, nodeState *schema.NodeStateDB) error {
var id int64 var id int64
if err := sq.Select("id").From("node"). if err := sq.Select("id").From("node").
@@ -203,7 +188,7 @@ func (r *NodeRepository) UpdateNodeState(hostname string, cluster string, nodeSt
cclog.Errorf("Error while getting subcluster for node '%s' in cluster '%s': %v", hostname, cluster, err) cclog.Errorf("Error while getting subcluster for node '%s' in cluster '%s': %v", hostname, cluster, err)
return err return err
} }
node := schema.Node{ node := schema.NodeDB{
Hostname: hostname, Cluster: cluster, SubCluster: subcluster, Hostname: hostname, Cluster: cluster, SubCluster: subcluster,
} }
id, err = r.AddNode(&node) id, err = r.AddNode(&node)
@@ -220,6 +205,8 @@ func (r *NodeRepository) UpdateNodeState(hostname string, cluster string, nodeSt
} }
} }
nodeState.NodeID = id
_, err := r.DB.NamedExec(NamedNodeStateInsert, nodeState) _, err := r.DB.NamedExec(NamedNodeStateInsert, nodeState)
if err != nil { if err != nil {
cclog.Errorf("Error while adding node state for '%v' to database", hostname) cclog.Errorf("Error while adding node state for '%v' to database", hostname)
@@ -254,9 +241,11 @@ func (r *NodeRepository) QueryNodes(
ctx context.Context, ctx context.Context,
filters []*model.NodeFilter, filters []*model.NodeFilter,
order *model.OrderByInput, // Currently unused! order *model.OrderByInput, // Currently unused!
) ([]*model.Node, error) { ) ([]*schema.Node, error) {
query, qerr := AccessCheck(ctx, query, qerr := AccessCheck(ctx,
sq.Select("node.hostname", "node.cluster", "node.subcluster", "node_state.node_state", "node_state.health_state", "MAX(node_state.time_stamp)").From("node_state").Join("node ON nodes_state.node_id = node.id").GroupBy("node_state.node_id")) sq.Select("node.hostname", "node.cluster", "node.subcluster", "node_state.node_state",
"node_state.health_state", "MAX(node_state.time_stamp)").From("node_state").
Join("node ON nodes_state.node_id = node.id").GroupBy("node_state.node_id"))
if qerr != nil { if qerr != nil {
return nil, qerr return nil, qerr
} }
@@ -271,8 +260,8 @@ func (r *NodeRepository) QueryNodes(
if f.Subcluster != nil { if f.Subcluster != nil {
query = buildStringCondition("node.subcluster", f.Subcluster, query) query = buildStringCondition("node.subcluster", f.Subcluster, query)
} }
if f.NodeState != nil { if f.SchedulerState != nil {
query = query.Where("node.node_state = ?", f.NodeState) query = query.Where("node.node_state = ?", f.SchedulerState)
} }
if f.HealthState != nil { if f.HealthState != nil {
query = query.Where("node.health_state = ?", f.HealthState) query = query.Where("node.health_state = ?", f.HealthState)
@@ -286,9 +275,9 @@ func (r *NodeRepository) QueryNodes(
return nil, err return nil, err
} }
nodes := make([]*model.Node, 0, 50) nodes := make([]*schema.Node, 0, 50)
for rows.Next() { for rows.Next() {
node := model.Node{} node := schema.Node{}
if err := rows.Scan(&node.Hostname, &node.Cluster, &node.SubCluster, if err := rows.Scan(&node.Hostname, &node.Cluster, &node.SubCluster,
&node.NodeState, &node.HealthState); err != nil { &node.NodeState, &node.HealthState); err != nil {

View File

@@ -0,0 +1,190 @@
// Copyright (C) NHR@FAU, University Erlangen-Nuremberg.
// All rights reserved. This file is part of cc-backend.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repository
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"time"
"github.com/ClusterCockpit/cc-backend/internal/config"
"github.com/ClusterCockpit/cc-backend/pkg/archive"
ccconf "github.com/ClusterCockpit/cc-lib/ccConfig"
cclog "github.com/ClusterCockpit/cc-lib/ccLogger"
"github.com/ClusterCockpit/cc-lib/schema"
_ "github.com/mattn/go-sqlite3"
)
func nodeTestSetup(t *testing.T) {
const testconfig = `{
"main": {
"addr": "0.0.0.0:8080",
"validate": false,
"apiAllowedIPs": [
"*"
]
},
"archive": {
"kind": "file",
"path": "./var/job-archive"
},
"auth": {
"jwts": {
"max-age": "2m"
}
},
"clusters": [
{
"name": "testcluster",
"metricDataRepository": {"kind": "test", "url": "bla:8081"},
"filterRanges": {
"numNodes": { "from": 1, "to": 64 },
"duration": { "from": 0, "to": 86400 },
"startTime": { "from": "2022-01-01T00:00:00Z", "to": null }
}
}
]
}`
const testclusterJSON = `{
"name": "testcluster",
"subClusters": [
{
"name": "sc1",
"nodes": "host123,host124,host125",
"processorType": "Intel Core i7-4770",
"socketsPerNode": 1,
"coresPerSocket": 4,
"threadsPerCore": 2,
"flopRateScalar": {
"unit": {
"prefix": "G",
"base": "F/s"
},
"value": 14
},
"flopRateSimd": {
"unit": {
"prefix": "G",
"base": "F/s"
},
"value": 112
},
"memoryBandwidth": {
"unit": {
"prefix": "G",
"base": "B/s"
},
"value": 24
},
"numberOfNodes": 70,
"topology": {
"node": [0, 1, 2, 3, 4, 5, 6, 7],
"socket": [[0, 1, 2, 3, 4, 5, 6, 7]],
"memoryDomain": [[0, 1, 2, 3, 4, 5, 6, 7]],
"die": [[0, 1, 2, 3, 4, 5, 6, 7]],
"core": [[0], [1], [2], [3], [4], [5], [6], [7]]
}
}
],
"metricConfig": [
{
"name": "load_one",
"unit": { "base": ""},
"scope": "node",
"timestep": 60,
"aggregation": "avg",
"peak": 8,
"normal": 0,
"caution": 0,
"alert": 0
}
]
}`
cclog.Init("debug", true)
tmpdir := t.TempDir()
jobarchive := filepath.Join(tmpdir, "job-archive")
if err := os.Mkdir(jobarchive, 0o777); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(jobarchive, "version.txt"),
fmt.Appendf(nil, "%d", 2), 0o666); err != nil {
t.Fatal(err)
}
if err := os.Mkdir(filepath.Join(jobarchive, "testcluster"),
0o777); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(jobarchive, "testcluster", "cluster.json"),
[]byte(testclusterJSON), 0o666); err != nil {
t.Fatal(err)
}
dbfilepath := filepath.Join(tmpdir, "test.db")
err := MigrateDB("sqlite3", dbfilepath)
if err != nil {
t.Fatal(err)
}
cfgFilePath := filepath.Join(tmpdir, "config.json")
if err := os.WriteFile(cfgFilePath, []byte(testconfig), 0o666); err != nil {
t.Fatal(err)
}
ccconf.Init(cfgFilePath)
// Load and check main configuration
if cfg := ccconf.GetPackageConfig("main"); cfg != nil {
if clustercfg := ccconf.GetPackageConfig("clusters"); clustercfg != nil {
config.Init(cfg, clustercfg)
} else {
cclog.Abort("Cluster configuration must be present")
}
} else {
cclog.Abort("Main configuration must be present")
}
archiveCfg := fmt.Sprintf("{\"kind\": \"file\",\"path\": \"%s\"}", jobarchive)
Connect("sqlite3", dbfilepath)
if err := archive.Init(json.RawMessage(archiveCfg), config.Keys.DisableArchive); err != nil {
t.Fatal(err)
}
}
func TestUpdateNodeState(t *testing.T) {
nodeTestSetup(t)
nodeState := schema.NodeStateDB{
TimeStamp: time.Now().Unix(), NodeState: "allocated",
CpusAllocated: 72,
MemoryAllocated: 480,
GpusAllocated: 0,
HealthState: schema.MonitoringStateFull,
JobsRunning: 1,
}
repo := GetNodeRepository()
err := repo.UpdateNodeState("host124", "testcluster", &nodeState)
if err != nil {
return
}
node, err := repo.GetNode("host124", "testcluster", false)
if err != nil {
return
}
if node.NodeState != "allocated" {
t.Errorf("wrong node state\ngot: %s \nwant: allocated ", node.NodeState)
}
}