1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
15 "git.arvados.org/arvados.git/sdk/go/arvados"
16 "git.arvados.org/arvados.git/sdk/go/arvadosclient"
17 "git.arvados.org/arvados.git/sdk/go/arvadostest"
18 "git.arvados.org/arvados.git/sdk/go/keepclient"
22 func Test(t *testing.T) {
26 var _ = check.Suite(&Suite{})
30 func (s *Suite) TearDownSuite(c *check.C) {
31 // Undo any changes/additions to the database so they don't affect subsequent tests.
32 arvadostest.ResetEnv()
35 func (s *Suite) SetUpSuite(c *check.C) {
36 arvadostest.StartAPI()
37 arvadostest.StartKeep(2, true)
39 // Get the various arvados, arvadosclient, and keep client objects
40 ac := arvados.NewClientFromEnv()
41 arv, err := arvadosclient.MakeArvadosClient()
42 c.Assert(err, check.Equals, nil)
43 arv.ApiToken = arvadostest.ActiveToken
44 kc, err := keepclient.MakeKeepClient(arv)
45 c.Assert(err, check.Equals, nil)
47 standardE4sV3JSON := `{
48 "Name": "Standard_E4s_v3",
49 "ProviderType": "Standard_E4s_v3",
52 "Scratch": 64000000000,
53 "IncludedScratch": 64000000000,
58 standardD32sV3JSON := `{
59 "Name": "Standard_D32s_v3",
60 "ProviderType": "Standard_D32s_v3",
63 "Scratch": 256000000000,
64 "IncludedScratch": 256000000000,
70 standardA1V2JSON := `{
72 "ProviderType": "Standard_A1_v2",
75 "Scratch": 10000000000,
76 "IncludedScratch": 10000000000,
82 standardA2V2JSON := `{
84 "ProviderType": "Standard_A2_v2",
87 "Scratch": 20000000000,
88 "IncludedScratch": 20000000000,
98 "size": "Standard_D1_v2"
100 "total_cpu_cores": 1,
101 "total_ram_mb": 3418,
102 "total_scratch_mb": 51170
106 // Our fixtures do not actually contain file contents. Populate the log collections we're going to use with the node.json file
107 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedContainerRequestUUID, arvadostest.LogCollectionUUID, standardE4sV3JSON)
108 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedContainerRequestUUID2, arvadostest.LogCollectionUUID2, standardD32sV3JSON)
110 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsContainerRequest1UUID, arvadostest.DiagnosticsContainerRequest1LogCollectionUUID, standardA1V2JSON)
111 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsContainerRequest2UUID, arvadostest.DiagnosticsContainerRequest2LogCollectionUUID, standardA1V2JSON)
112 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsHasher1ContainerRequestUUID, arvadostest.Hasher1LogCollectionUUID, standardA1V2JSON)
113 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsHasher2ContainerRequestUUID, arvadostest.Hasher2LogCollectionUUID, standardA2V2JSON)
114 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsHasher3ContainerRequestUUID, arvadostest.Hasher3LogCollectionUUID, legacyD1V2JSON)
117 func createNodeJSON(c *check.C, arv *arvadosclient.ArvadosClient, ac *arvados.Client, kc *keepclient.KeepClient, crUUID string, logUUID string, nodeJSON string) {
119 var cr arvados.ContainerRequest
120 err := ac.RequestAndDecode(&cr, "GET", "arvados/v1/container_requests/"+crUUID, nil, nil)
121 c.Assert(err, check.Equals, nil)
122 c.Assert(cr.LogUUID, check.Equals, logUUID)
124 // Get the log collection
125 var coll arvados.Collection
126 err = ac.RequestAndDecode(&coll, "GET", "arvados/v1/collections/"+cr.LogUUID, nil, nil)
127 c.Assert(err, check.IsNil)
129 // Create a node.json file -- the fixture doesn't actually contain the contents of the collection.
130 fs, err := coll.FileSystem(ac, kc)
131 c.Assert(err, check.IsNil)
132 f, err := fs.OpenFile("node.json", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
133 c.Assert(err, check.IsNil)
134 _, err = io.WriteString(f, nodeJSON)
135 c.Assert(err, check.IsNil)
137 c.Assert(err, check.IsNil)
139 // Flush the data to Keep
140 mtxt, err := fs.MarshalManifest(".")
141 c.Assert(err, check.IsNil)
142 c.Assert(mtxt, check.NotNil)
144 // Update collection record
145 err = ac.RequestAndDecode(&coll, "PUT", "arvados/v1/collections/"+cr.LogUUID, nil, map[string]interface{}{
146 "collection": map[string]interface{}{
147 "manifest_text": mtxt,
150 c.Assert(err, check.IsNil)
153 func (*Suite) TestUsage(c *check.C) {
154 var stdout, stderr bytes.Buffer
155 exitcode := Command.RunCommand("costanalyzer.test", []string{"-help", "-log-level=debug"}, &bytes.Buffer{}, &stdout, &stderr)
156 c.Check(exitcode, check.Equals, 1)
157 c.Check(stdout.String(), check.Equals, "")
158 c.Check(stderr.String(), check.Matches, `(?ms).*Usage:.*`)
161 func (*Suite) TestContainerRequestUUID(c *check.C) {
162 var stdout, stderr bytes.Buffer
163 // Run costanalyzer with 1 container request uuid
164 exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedContainerRequestUUID, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
165 c.Check(exitcode, check.Equals, 0)
166 c.Assert(stderr.String(), check.Matches, "(?ms).*supplied uuids in .*")
168 uuidReport, err := ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID + ".csv")
169 c.Assert(err, check.IsNil)
170 c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,7.01302889")
171 re := regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
172 matches := re.FindStringSubmatch(stderr.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
174 aggregateCostReport, err := ioutil.ReadFile(matches[1])
175 c.Assert(err, check.IsNil)
177 c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,7.01302889")
180 func (*Suite) TestDoubleContainerRequestUUID(c *check.C) {
181 var stdout, stderr bytes.Buffer
182 // Run costanalyzer with 2 container request uuids
183 exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedContainerRequestUUID, "-uuid", arvadostest.CompletedContainerRequestUUID2, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
184 c.Check(exitcode, check.Equals, 0)
185 c.Assert(stderr.String(), check.Matches, "(?ms).*supplied uuids in .*")
187 uuidReport, err := ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID + ".csv")
188 c.Assert(err, check.IsNil)
189 c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,7.01302889")
191 uuidReport2, err := ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID2 + ".csv")
192 c.Assert(err, check.IsNil)
193 c.Check(string(uuidReport2), check.Matches, "(?ms).*TOTAL,,,,,,,,,42.27031111")
195 re := regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
196 matches := re.FindStringSubmatch(stderr.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
198 aggregateCostReport, err := ioutil.ReadFile(matches[1])
199 c.Assert(err, check.IsNil)
201 c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,49.28334000")
205 // Now move both container requests into an existing project, and then re-run
206 // the analysis with the project uuid. The results should be identical.
207 ac := arvados.NewClientFromEnv()
208 var cr arvados.ContainerRequest
209 err = ac.RequestAndDecode(&cr, "PUT", "arvados/v1/container_requests/"+arvadostest.CompletedContainerRequestUUID, nil, map[string]interface{}{
210 "container_request": map[string]interface{}{
211 "owner_uuid": arvadostest.AProjectUUID,
214 c.Assert(err, check.IsNil)
215 err = ac.RequestAndDecode(&cr, "PUT", "arvados/v1/container_requests/"+arvadostest.CompletedContainerRequestUUID2, nil, map[string]interface{}{
216 "container_request": map[string]interface{}{
217 "owner_uuid": arvadostest.AProjectUUID,
220 c.Assert(err, check.IsNil)
222 // Run costanalyzer with the project uuid
223 exitcode = Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.AProjectUUID, "-cache=false", "-log-level", "debug", "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
224 c.Check(exitcode, check.Equals, 0)
225 c.Assert(stderr.String(), check.Matches, "(?ms).*supplied uuids in .*")
227 uuidReport, err = ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID + ".csv")
228 c.Assert(err, check.IsNil)
229 c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,7.01302889")
231 uuidReport2, err = ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID2 + ".csv")
232 c.Assert(err, check.IsNil)
233 c.Check(string(uuidReport2), check.Matches, "(?ms).*TOTAL,,,,,,,,,42.27031111")
235 re = regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
236 matches = re.FindStringSubmatch(stderr.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
238 aggregateCostReport, err = ioutil.ReadFile(matches[1])
239 c.Assert(err, check.IsNil)
241 c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,49.28334000")
244 func (*Suite) TestMultipleContainerRequestUUIDWithReuse(c *check.C) {
245 var stdout, stderr bytes.Buffer
246 // Run costanalyzer with 2 container request uuids
247 exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedDiagnosticsContainerRequest1UUID, "-uuid", arvadostest.CompletedDiagnosticsContainerRequest2UUID, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
248 c.Check(exitcode, check.Equals, 0)
249 c.Assert(stderr.String(), check.Matches, "(?ms).*supplied uuids in .*")
251 uuidReport, err := ioutil.ReadFile("results/" + arvadostest.CompletedDiagnosticsContainerRequest1UUID + ".csv")
252 c.Assert(err, check.IsNil)
253 c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,0.00916192")
255 uuidReport2, err := ioutil.ReadFile("results/" + arvadostest.CompletedDiagnosticsContainerRequest2UUID + ".csv")
256 c.Assert(err, check.IsNil)
257 c.Check(string(uuidReport2), check.Matches, "(?ms).*TOTAL,,,,,,,,,0.00588088")
259 re := regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
260 matches := re.FindStringSubmatch(stderr.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
262 aggregateCostReport, err := ioutil.ReadFile(matches[1])
263 c.Assert(err, check.IsNil)
265 c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,0.01492030")