diff --git a/NOTICE.release b/NOTICE.release index 9a2bfd1..000e62c 100644 --- a/NOTICE.release +++ b/NOTICE.release @@ -140,8 +140,8 @@ SOFTWARE. ------------------------------------------------------------------------------ -This work uses the 'gopkg.in/yaml.v2' module for Go -(https://github.com/go-yaml/yaml) which contains the following NOTICE and is +This work uses the 'go.yaml.in/yaml/v3' module for Go +(https://github.com/yaml/go-yaml) which contains the following NOTICE and is licensed under the Apache 2.0 license (see LICENSE): Copyright 2011-2016 Canonical Ltd. @@ -161,7 +161,7 @@ licensed under the Apache 2.0 license (see LICENSE): ------------------------------------------------------------------------------ This work includes works derived from the libyaml project as part of the -'gopkg.in/yaml.v2' module for Go: +'go.yaml.in/yaml/v3' module for Go: Copyright (c) 2006 Kirill Simonov diff --git a/cmd/cmgr/schemas.go b/cmd/cmgr/schemas.go index 850bf08..ee8312f 100644 --- a/cmd/cmgr/schemas.go +++ b/cmd/cmgr/schemas.go @@ -7,7 +7,7 @@ import ( "io/ioutil" "path/filepath" - "gopkg.in/yaml.v2" + "go.yaml.in/yaml/v3" "github.com/picoCTF/cmgr/cmgr" ) diff --git a/cmgr/cpu.go b/cmgr/cpu.go new file mode 100644 index 0000000..6e2d1a2 --- /dev/null +++ b/cmgr/cpu.go @@ -0,0 +1,29 @@ +// Adapted from ArmyCyberInstitute/cmgr bef2185 (#60) +package cmgr + +import ( + "fmt" + "math/big" +) + +const nanoCPUsPerCPU int64 = 1_000_000_000 + +// parseNanoCPUs converts Docker's decimal --cpus representation into the +// NanoCPUs integer accepted by the Engine API. Values must resolve to a whole +// number of nanoseconds and fit in an int64. +func parseNanoCPUs(value string) (int64, error) { + cpus, ok := new(big.Rat).SetString(value) + if !ok { + return 0, fmt.Errorf("failed to parse %q as a rational number", value) + } + + nanoCPUs := new(big.Rat).Mul(cpus, big.NewRat(nanoCPUsPerCPU, 1)) + if !nanoCPUs.IsInt() { + return 0, fmt.Errorf("CPU value %q is more precise than one NanoCPU", value) + } + if !nanoCPUs.Num().IsInt64() { + return 0, fmt.Errorf("CPU value %q exceeds the supported range", value) + } + + return nanoCPUs.Num().Int64(), nil +} diff --git a/cmgr/cpu_test.go b/cmgr/cpu_test.go new file mode 100644 index 0000000..726e059 --- /dev/null +++ b/cmgr/cpu_test.go @@ -0,0 +1,46 @@ +// Adapted from ArmyCyberInstitute/cmgr bef2185 (#60) +package cmgr + +import "testing" + +func TestParseNanoCPUs(t *testing.T) { + tests := []struct { + value string + want int64 + }{ + {value: "0", want: 0}, + {value: "0.001", want: 1_000_000}, + {value: "0.5", want: 500_000_000}, + {value: "1", want: 1_000_000_000}, + {value: "1.25", want: 1_250_000_000}, + {value: "3/2", want: 1_500_000_000}, + {value: "-0.5", want: -500_000_000}, + } + + for _, test := range tests { + t.Run(test.value, func(t *testing.T) { + got, err := parseNanoCPUs(test.value) + if err != nil { + t.Fatalf("parseNanoCPUs(%q) failed: %s", test.value, err) + } + if got != test.want { + t.Fatalf("parseNanoCPUs(%q) = %d, want %d", test.value, got, test.want) + } + }) + } +} + +func TestParseNanoCPUsRejectsInvalidValues(t *testing.T) { + for _, value := range []string{ + "", + "cpu", + "0.0000000001", + "9223372037", + } { + t.Run(value, func(t *testing.T) { + if _, err := parseNanoCPUs(value); err == nil { + t.Fatalf("parseNanoCPUs(%q) unexpectedly succeeded", value) + } + }) + } +} diff --git a/cmgr/docker.go b/cmgr/docker.go index 3ff4a0e..b848923 100644 --- a/cmgr/docker.go +++ b/cmgr/docker.go @@ -23,7 +23,6 @@ import ( "time" "github.com/containerd/errdefs" - dockeropts "github.com/docker/cli/opts" "github.com/docker/go-units" "github.com/jmoiron/sqlx" "github.com/moby/moby/api/types/container" @@ -937,7 +936,7 @@ func (m *Manager) startContainers(build *BuildMetadata, instance *InstanceMetada if hasContainerOpts { hConfig.Init = &cOpts.Init if cOpts.Cpus != "" { - nanoCpus, err := dockeropts.ParseCPUs(cOpts.Cpus) + nanoCpus, err := parseNanoCPUs(cOpts.Cpus) if err != nil { return err } diff --git a/cmgr/loader.go b/cmgr/loader.go index 540dd2a..9548ae7 100644 --- a/cmgr/loader.go +++ b/cmgr/loader.go @@ -9,7 +9,6 @@ import ( "strconv" "strings" - dockeropts "github.com/docker/cli/opts" "github.com/docker/go-units" ) @@ -337,7 +336,7 @@ func (m *Manager) validateMetadata(md *ChallengeMetadata) error { } if opts.Cpus != "" { - _, err := dockeropts.ParseCPUs(opts.Cpus) + _, err := parseNanoCPUs(opts.Cpus) if err != nil { lastErr = fmt.Errorf("%serror parsing cpus container option: %v", hostStr, err) m.log.error(lastErr) diff --git a/cmgr/loader_markdown.go b/cmgr/loader_markdown.go index 87764b5..3ab84ba 100644 --- a/cmgr/loader_markdown.go +++ b/cmgr/loader_markdown.go @@ -20,7 +20,7 @@ import ( "github.com/yuin/goldmark/ast" goldmarktext "github.com/yuin/goldmark/text" "golang.org/x/net/html" - "gopkg.in/yaml.v2" + "go.yaml.in/yaml/v3" ) var ( diff --git a/go.mod b/go.mod index 6f7bb1d..8ba556c 100644 --- a/go.mod +++ b/go.mod @@ -5,15 +5,14 @@ go 1.26.0 require ( github.com/JohannesKaufmann/html-to-markdown/v2 v2.5.2 github.com/containerd/errdefs v1.0.0 - github.com/docker/cli v29.6.2+incompatible github.com/docker/go-units v0.5.0 github.com/jmoiron/sqlx v1.4.0 github.com/mattn/go-sqlite3 v1.14.48 github.com/moby/moby/api v1.55.0 github.com/moby/moby/client v0.5.0 github.com/yuin/goldmark v1.8.4 + go.yaml.in/yaml/v3 v3.0.5 golang.org/x/net v0.57.0 - gopkg.in/yaml.v2 v2.4.0 ) require ( diff --git a/go.sum b/go.sum index a70cf83..1aa2bcd 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v29.6.2+incompatible h1:/bjePvcbbFTnRrMfWJBY7AjfICdsiLVgHn6LwTVOcqw= -github.com/docker/cli v29.6.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -37,10 +35,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= @@ -58,8 +52,6 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -82,15 +74,12 @@ go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4A go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0= go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -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/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=