diff --git a/exporter/fixtures/sinfo_dataparser.json b/exporter/fixtures/sinfo_dataparser.json new file mode 100644 index 0000000..39bb74a --- /dev/null +++ b/exporter/fixtures/sinfo_dataparser.json @@ -0,0 +1,215 @@ +{ + "meta": { + "plugins": { + "data_parser": "data_parser\/v0.0.39", + "accounting_storage": "accounting_storage\/none" + }, + "command": [ + "sinfo", + "-N", + "--json" + ], + "Slurm": { + "version": { + "major": 23, + "micro": 5, + "minor": 2 + }, + "release": "23.02.5" + } + }, + "sinfo": [ + { + "port": 6818, + "node": { + "state": [ + "ALLOCATED" + ] + }, + "nodes": { + "allocated": 1, + "idle": 0, + "other": 0, + "total": 1, + "hostnames": [ + ], + "addresses": [ + ], + "nodes": [ + "localhost" + ] + }, + "cpus": { + "allocated": 1, + "idle": 0, + "other": 0, + "total": 1, + "minimum": 1, + "maximum": 1, + "load": { + "minimum": 78, + "maximum": 78 + }, + "per_node": { + "max": { + "set": false, + "infinite": true, + "number": 0 + } + } + }, + "sockets": { + "minimum": 1, + "maximum": 1 + }, + "cores": { + "minimum": 1, + "maximum": 1 + }, + "threads": { + "minimum": 1, + "maximum": 1 + }, + "disk": { + "minimum": 0, + "maximum": 0 + }, + "memory": { + "minimum": 1, + "maximum": 1, + "free": { + "minimum": { + "set": true, + "infinite": false, + "number": 227 + }, + "maximum": { + "set": true, + "infinite": false, + "number": 227 + } + }, + "allocated": 1 + }, + "weight": { + "minimum": 1, + "maximum": 1 + }, + "features": { + "total": "", + "active": "" + }, + "gres": { + "total": "", + "used": "" + }, + "cluster": "", + "comment": "", + "extra": "", + "reason": { + "description": "", + "time": 0, + "user": "" + }, + "reservation": "", + "partition": { + "nodes": { + "allowed_allocation": "", + "configured": "localhost", + "total": 1 + }, + "accounts": { + "allowed": "", + "deny": "" + }, + "groups": { + "allowed": "" + }, + "qos": { + "allowed": "", + "deny": "", + "assigned": "" + }, + "alternate": "", + "tres": { + "billing_weights": "", + "configured": "cpu=1,mem=1M,node=1,billing=1" + }, + "cluster": "", + "cpus": { + "task_binding": 0, + "total": 1 + }, + "defaults": { + "memory_per_cpu": 0, + "time": { + "set": false, + "infinite": false, + "number": 0 + }, + "job": "" + }, + "grace_time": 0, + "maximums": { + "cpus_per_node": { + "set": false, + "infinite": true, + "number": 0 + }, + "cpus_per_socket": { + "set": false, + "infinite": true, + "number": 0 + }, + "memory_per_cpu": 0, + "nodes": { + "set": false, + "infinite": true, + "number": 0 + }, + "shares": 1, + "time": { + "set": false, + "infinite": true, + "number": 0 + }, + "over_time_limit": { + "set": false, + "infinite": false, + "number": 0 + } + }, + "minimums": { + "nodes": 0 + }, + "name": "debug", + "node_sets": "", + "priority": { + "job_factor": 1, + "tier": 1 + }, + "timeouts": { + "resume": { + "set": false, + "infinite": false, + "number": 0 + }, + "suspend": { + "set": false, + "infinite": false, + "number": 0 + } + }, + "suspend_time": { + "set": false, + "infinite": false, + "number": 0 + } + } + } + ], + "warnings": [ + ], + "errors": [ + ] + } diff --git a/exporter/fixtures/sinfo_dataparser.json.license b/exporter/fixtures/sinfo_dataparser.json.license new file mode 100644 index 0000000..d8f6e93 --- /dev/null +++ b/exporter/fixtures/sinfo_dataparser.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2023 Rivos Inc. + +SPDX-License-Identifier: Apache-2.0 diff --git a/exporter/main_test.go b/exporter/main_test.go index 8504060..6caeb4e 100644 --- a/exporter/main_test.go +++ b/exporter/main_test.go @@ -63,7 +63,7 @@ func TestNewConfig_Default(t *testing.T) { assert := assert.New(t) config, err := NewConfig(new(CliFlags)) assert.Nil(err) - assert.Equal([]string{"sinfo", "--json"}, config.cliOpts.sinfo) + assert.Equal([]string{"sinfo", "-N", "--json"}, config.cliOpts.sinfo) assert.Equal([]string{"squeue", "--json"}, config.cliOpts.squeue) assert.Equal([]string{"scontrol", "show", "lic", "--json"}, config.cliOpts.lic) assert.Equal(uint64(10), config.TraceConf.rate) diff --git a/exporter/nodes.go b/exporter/nodes.go index 4d857dd..062e601 100644 --- a/exporter/nodes.go +++ b/exporter/nodes.go @@ -32,6 +32,125 @@ type NodeMetric struct { Weight float64 `json:"weight"` } +type sinfoDataParserResponse struct { + Meta struct { + Plugins map[string]string `json:"plugins"` + } `json:"meta"` + SlurmVersion struct { + Version struct { + Major int `json:"major"` + Micro int `json:"micro"` + Minor int `json:"minor"` + } `json:"version"` + Release string `json:"release"` + } `json:"Slurm"` + Sinfo []struct { + Node struct { + State []string `json:"state"` + } `json:"node"` + Nodes struct { + Allocated int `json:"allocated"` + Idle int `json:"idle"` + Other int `json:"other"` + Total int `json:"total"` + Nodes []string `json:"nodes"` + } `json:"nodes"` + Cpus struct { + Allocated int `json:"allocated"` + Idle int `json:"idle"` + Other int `json:"other"` + Total int `json:"total"` + } + Memory struct { + Minimum int `json:"minimum"` + Maximum int `json:"maximum"` + Allocated int `json:"allocated"` + Free struct { + Minimum struct { + Set bool `json:"set"` + Number int `json:"number"` + } `json:"minimum"` + Maximum struct { + Set bool `json:"set"` + Number int `json:"number"` + } `json:"maximum"` + } `json:"free"` + } + Partition struct { + Name string `json:"name"` + Alternate string `json:"alternate"` + } `json:"partition"` + } `json:"sinfo"` +} + +type DataParserJsonFetcher struct { + scraper SlurmByteScraper + errorCounter prometheus.Counter + duration time.Duration + cache *AtomicThrottledCache[NodeMetric] +} + +func (dpj *DataParserJsonFetcher) fetch() ([]NodeMetric, error) { + squeue := new(sinfoDataParserResponse) + cliJson, err := dpj.scraper.FetchRawBytes() + if err != nil { + dpj.errorCounter.Inc() + return nil, err + } + if err := json.Unmarshal(cliJson, squeue); err != nil { + dpj.errorCounter.Inc() + return nil, err + } + nodeMetrics := make([]NodeMetric, 0) + for _, entry := range squeue.Sinfo { + nodes := entry.Nodes + // validate single node parse + if nodes.Total != 1 { + dpj.errorCounter.Inc() + return nil, fmt.Errorf("must contain only 1 node per entry, please use the -N option exp. `sinfo -N --json`") + } + freeMemSet := entry.Memory.Free.Maximum.Set && entry.Memory.Free.Minimum.Set + if freeMemSet && entry.Memory.Free.Minimum.Number != entry.Memory.Free.Maximum.Number { + dpj.errorCounter.Inc() + slog.Error("unable to scrape free mem set") + } + if entry.Memory.Minimum != entry.Memory.Maximum { + dpj.errorCounter.Inc() + return nil, fmt.Errorf("must contain only 1 node per entry, please use the -N option exp. `sinfo -N --json`") + } + metric := NodeMetric{ + Hostname: nodes.Nodes[0], + Cpus: float64(entry.Cpus.Total), + RealMemory: float64(entry.Memory.Maximum), + FreeMemory: float64(entry.Memory.Free.Maximum.Number), + State: strings.Join(entry.Node.State, "&"), + } + if !slices.Contains(metric.Partitions, entry.Partition.Name) { + metric.Partitions = append(metric.Partitions, entry.Partition.Name) + } + if entry.Partition.Alternate != "" && !slices.Contains(metric.Partitions, entry.Partition.Alternate) { + metric.Partitions = append(metric.Partitions, entry.Partition.Alternate) + } + nodeMetrics = append(nodeMetrics, metric) + } + return nodeMetrics, nil +} + +func (dpj *DataParserJsonFetcher) FetchMetrics() ([]NodeMetric, error) { + t := time.Now() + metrics, err := dpj.cache.FetchOrThrottle(dpj.fetch) + dpj.duration = time.Since(t) + return metrics, err +} + +func (dpj *DataParserJsonFetcher) ScrapeDuration() time.Duration { + return dpj.duration +} + +func (dpj *DataParserJsonFetcher) ScrapeError() prometheus.Counter { + return dpj.errorCounter +} + type sinfoResponse struct { Meta struct { SlurmVersion struct { diff --git a/exporter/nodes_test.go b/exporter/nodes_test.go index 9bb19cb..3a01a71 100644 --- a/exporter/nodes_test.go +++ b/exporter/nodes_test.go @@ -15,6 +15,7 @@ import ( var MockNodeInfoScraper = &MockScraper{fixture: "fixtures/sinfo_out.json"} var MockNodeInfoDataParserScraper = &MockScraper{fixture: "fixtures/sinfo_dataparser.json"} +var MockNodeDataParserScraper = &MockScraper{fixture: "fixtures/sinfo_dataparser.json"} func TestNewNodeCollector(t *testing.T) { assert := assert.New(t) @@ -92,6 +93,18 @@ func TestNodeSummaryMemoryMetrics(t *testing.T) { assert.Equal(2e+06, metrics.RealMemory) } +func TestDataParserNodeSummaryMemoryMetrics(t *testing.T) { + assert := assert.New(t) + fetcher := DataParserJsonFetcher{scraper: MockNodeDataParserScraper, errorCounter: prometheus.NewCounter(prometheus.CounterOpts{}), cache: NewAtomicThrottledCache[NodeMetric](1)} + nodeMetrics, err := fetcher.FetchMetrics() + fmt.Println(nodeMetrics) + assert.Nil(err) + metrics := fetchNodeTotalMemMetrics(nodeMetrics) + assert.Equal(114688., metrics.AllocMemory) + assert.Equal(1.823573e+06, metrics.FreeMemory) + assert.Equal(2e+06, metrics.RealMemory) +} + func TestNodeCollector(t *testing.T) { assert := assert.New(t) config, err := NewConfig(new(CliFlags)) diff --git a/exporter/server.go b/exporter/server.go index ec0bccd..f752884 100644 --- a/exporter/server.go +++ b/exporter/server.go @@ -69,7 +69,7 @@ func NewConfig(cliFlags *CliFlags) (*Config, error) { // defaults cliOpts := CliOpts{ squeue: []string{"squeue", "--json"}, - sinfo: []string{"sinfo", "--json"}, + sinfo: []string{"sinfo", "-N", "--json"}, lic: []string{"scontrol", "show", "lic", "--json"}, sdiag: []string{"sdiag", "--json"}, licEnabled: cliFlags.SlurmLicEnabled, diff --git a/go.mod b/go.mod index 01aa63c..da106be 100644 --- a/go.mod +++ b/go.mod @@ -1,26 +1,48 @@ module github.com/rivosinc/prometheus-slurm-exporter -go 1.20 +go 1.21.0 + +toolchain go1.22.2 require ( github.com/prometheus/client_golang v1.16.0 github.com/prometheus/client_model v0.3.0 github.com/stretchr/testify v1.8.4 - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cilium/ebpf v0.14.0 // indirect + github.com/cosiner/argv v0.1.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d // indirect + github.com/go-delve/delve v1.22.1 // indirect + github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-dap v0.12.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/text v0.2.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect - golang.org/x/sys v0.12.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/spf13/cobra v1.8.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + go.starlark.net v0.0.0-20240411212711-9b43f0afd521 // indirect + golang.org/x/arch v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 0e1ddf4..e149d05 100644 --- a/go.sum +++ b/go.sum @@ -2,9 +2,23 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cilium/ebpf v0.14.0 h1:0PsxAjO6EjI1rcT+rkp6WcCnE0ZvfkXBYiMedJtrSUs= +github.com/cilium/ebpf v0.14.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso= +github.com/cosiner/argv v0.1.0 h1:BVDiEL32lwHukgJKP87btEPenzrrHUjajs/8yzaqcXg= +github.com/cosiner/argv v0.1.0/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d h1:hUWoLdw5kvo2xCsqlsIBMvWUc1QCSsCYD2J2+Fg6YoU= +github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d/go.mod h1:C7Es+DLenIpPc9J6IYw4jrK0h7S9bKj4DNl8+KxGEXU= +github.com/go-delve/delve v1.22.1 h1:LQSF2sv+lP3mmOzMkadl5HGQGgSS2bFg2tbyALqHu8Y= +github.com/go-delve/delve v1.22.1/go.mod h1:TfOb+G5H6YYKheZYAmA59ojoHbOimGfs5trbghHdLbM= +github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62 h1:IGtvsNyIuRjl04XAOFGACozgUD7A82UffYxZt4DWbvA= +github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62/go.mod h1:biJCRbqp51wS+I92HMqn5H8/A0PAhxn2vyOT+JqhiGI= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -12,9 +26,23 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-dap v0.12.0 h1:rVcjv3SyMIrpaOoTAdFDyHs99CwVOItIJGKLQFQhNeM= +github.com/google/go-dap v0.12.0/go.mod h1:tNjCASCm5cqePi/RVXXWEVqtnNLV1KTWtYOqu6rZNzc= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -27,21 +55,51 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.starlark.net v0.0.0-20240411212711-9b43f0afd521 h1:1Ufp2S2fPpj0RHIQ4rbzpCdPLCPkzdK7BaVFH3nkYBQ= +go.starlark.net v0.0.0-20240411212711-9b43f0afd521/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= +golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= +golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=