1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
16 "git.arvados.org/arvados.git/sdk/go/arvados"
17 "git.arvados.org/arvados.git/sdk/go/arvadosclient"
18 "git.arvados.org/arvados.git/sdk/go/arvadostest"
19 "git.arvados.org/arvados.git/sdk/go/keepclient"
23 func Test(t *testing.T) {
27 var _ = check.Suite(&Suite{})
31 func (s *Suite) TearDownSuite(c *check.C) {
32 // Undo any changes/additions to the database so they don't affect subsequent tests.
33 arvadostest.ResetEnv()
36 func (s *Suite) SetUpSuite(c *check.C) {
37 arvadostest.StartAPI()
38 arvadostest.StartKeep(2, true)
40 // Get the various arvados, arvadosclient, and keep client objects
41 ac := arvados.NewClientFromEnv()
42 arv, err := arvadosclient.MakeArvadosClient()
43 c.Assert(err, check.Equals, nil)
44 arv.ApiToken = arvadostest.ActiveToken
45 kc, err := keepclient.MakeKeepClient(arv)
46 c.Assert(err, check.Equals, nil)
48 standardE4sV3JSON := `{
49 "Name": "Standard_E4s_v3",
50 "ProviderType": "Standard_E4s_v3",
53 "Scratch": 64000000000,
54 "IncludedScratch": 64000000000,
59 standardD32sV3JSON := `{
60 "Name": "Standard_D32s_v3",
61 "ProviderType": "Standard_D32s_v3",
64 "Scratch": 256000000000,
65 "IncludedScratch": 256000000000,
71 standardA1V2JSON := `{
73 "ProviderType": "Standard_A1_v2",
76 "Scratch": 10000000000,
77 "IncludedScratch": 10000000000,
83 standardA2V2JSON := `{
85 "ProviderType": "Standard_A2_v2",
88 "Scratch": 20000000000,
89 "IncludedScratch": 20000000000,
95 // Our fixtures do not actually contain file contents. Populate the log collections we're going to use with the node.json file
96 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedContainerRequestUUID, arvadostest.LogCollectionUUID, standardE4sV3JSON)
97 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedContainerRequestUUID2, arvadostest.LogCollectionUUID2, standardD32sV3JSON)
99 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsContainerRequest1UUID, arvadostest.DiagnosticsContainerRequest1LogCollectionUUID, standardA1V2JSON)
100 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsContainerRequest2UUID, arvadostest.DiagnosticsContainerRequest2LogCollectionUUID, standardA1V2JSON)
101 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsHasher1ContainerRequestUUID, arvadostest.Hasher1LogCollectionUUID, standardA1V2JSON)
102 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsHasher2ContainerRequestUUID, arvadostest.Hasher2LogCollectionUUID, standardA2V2JSON)
103 createNodeJSON(c, arv, ac, kc, arvadostest.CompletedDiagnosticsHasher3ContainerRequestUUID, arvadostest.Hasher3LogCollectionUUID, standardA1V2JSON)
106 func createNodeJSON(c *check.C, arv *arvadosclient.ArvadosClient, ac *arvados.Client, kc *keepclient.KeepClient, crUUID string, logUUID string, nodeJSON string) {
108 var cr arvados.ContainerRequest
109 err := ac.RequestAndDecodeContext(context.Background(), &cr, "GET", "arvados/v1/container_requests/"+crUUID, nil, nil)
110 c.Assert(err, check.Equals, nil)
111 c.Assert(cr.LogUUID, check.Equals, logUUID)
113 // Get the log collection
114 var coll arvados.Collection
115 err = ac.RequestAndDecodeContext(context.Background(), &coll, "GET", "arvados/v1/collections/"+cr.LogUUID, nil, nil)
116 c.Assert(err, check.IsNil)
118 // Create a node.json file -- the fixture doesn't actually contain the contents of the collection.
119 fs, err := coll.FileSystem(ac, kc)
120 c.Assert(err, check.IsNil)
121 f, err := fs.OpenFile("node.json", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
122 c.Assert(err, check.IsNil)
123 _, err = io.WriteString(f, nodeJSON)
124 c.Assert(err, check.IsNil)
126 c.Assert(err, check.IsNil)
128 // Flush the data to Keep
129 mtxt, err := fs.MarshalManifest(".")
130 c.Assert(err, check.IsNil)
131 c.Assert(mtxt, check.NotNil)
133 // Update collection record
134 err = ac.RequestAndDecodeContext(context.Background(), &coll, "PUT", "arvados/v1/collections/"+cr.LogUUID, nil, map[string]interface{}{
135 "collection": map[string]interface{}{
136 "manifest_text": mtxt,
139 c.Assert(err, check.IsNil)
142 func (*Suite) TestUsage(c *check.C) {
143 var stdout, stderr bytes.Buffer
144 exitcode := Command.RunCommand("costanalyzer.test", []string{"-help", "-log-level=debug"}, &bytes.Buffer{}, &stdout, &stderr)
145 c.Check(exitcode, check.Equals, 1)
146 c.Check(stdout.String(), check.Equals, "")
147 c.Check(stderr.String(), check.Matches, `(?ms).*Usage:.*`)
150 func (*Suite) TestContainerRequestUUID(c *check.C) {
151 var stdout, stderr bytes.Buffer
152 // Run costanalyzer with 1 container request uuid
153 exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedContainerRequestUUID}, &bytes.Buffer{}, &stdout, &stderr)
154 c.Check(exitcode, check.Equals, 0)
155 c.Assert(stdout.String(), check.Matches, "(?ms).*supplied uuids in .*")
157 uuidReport, err := ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID + ".csv")
158 c.Assert(err, check.IsNil)
159 c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,7.01302889")
160 re := regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
161 matches := re.FindStringSubmatch(stdout.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
163 aggregateCostReport, err := ioutil.ReadFile(matches[1])
164 c.Assert(err, check.IsNil)
166 c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,7.01302889")
169 func (*Suite) TestDoubleContainerRequestUUID(c *check.C) {
170 var stdout, stderr bytes.Buffer
171 // Run costanalyzer with 2 container request uuids
172 exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedContainerRequestUUID, "-uuid", arvadostest.CompletedContainerRequestUUID2}, &bytes.Buffer{}, &stdout, &stderr)
173 c.Check(exitcode, check.Equals, 0)
174 c.Assert(stdout.String(), check.Matches, "(?ms).*supplied uuids in .*")
176 uuidReport, err := ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID + ".csv")
177 c.Assert(err, check.IsNil)
178 c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,7.01302889")
180 uuidReport2, err := ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID2 + ".csv")
181 c.Assert(err, check.IsNil)
182 c.Check(string(uuidReport2), check.Matches, "(?ms).*TOTAL,,,,,,,,,42.27031111")
184 re := regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
185 matches := re.FindStringSubmatch(stdout.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
187 aggregateCostReport, err := ioutil.ReadFile(matches[1])
188 c.Assert(err, check.IsNil)
190 c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,49.28334000")
194 // Now move both container requests into an existing project, and then re-run
195 // the analysis with the project uuid. The results should be identical.
196 ac := arvados.NewClientFromEnv()
197 var cr arvados.ContainerRequest
198 err = ac.RequestAndDecodeContext(context.Background(), &cr, "PUT", "arvados/v1/container_requests/"+arvadostest.CompletedContainerRequestUUID, nil, map[string]interface{}{
199 "container_request": map[string]interface{}{
200 "owner_uuid": arvadostest.AProjectUUID,
203 c.Assert(err, check.IsNil)
204 err = ac.RequestAndDecodeContext(context.Background(), &cr, "PUT", "arvados/v1/container_requests/"+arvadostest.CompletedContainerRequestUUID2, nil, map[string]interface{}{
205 "container_request": map[string]interface{}{
206 "owner_uuid": arvadostest.AProjectUUID,
209 c.Assert(err, check.IsNil)
211 // Run costanalyzer with the project uuid
212 exitcode = Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.AProjectUUID, "-cache=false", "-log-level", "debug"}, &bytes.Buffer{}, &stdout, &stderr)
213 c.Check(exitcode, check.Equals, 0)
214 c.Assert(stdout.String(), check.Matches, "(?ms).*supplied uuids in .*")
216 uuidReport, err = ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID + ".csv")
217 c.Assert(err, check.IsNil)
218 c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,7.01302889")
220 uuidReport2, err = ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID2 + ".csv")
221 c.Assert(err, check.IsNil)
222 c.Check(string(uuidReport2), check.Matches, "(?ms).*TOTAL,,,,,,,,,42.27031111")
224 re = regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
225 matches = re.FindStringSubmatch(stdout.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
227 aggregateCostReport, err = ioutil.ReadFile(matches[1])
228 c.Assert(err, check.IsNil)
230 c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,49.28334000")
233 func (*Suite) TestMultipleContainerRequestUUIDWithReuse(c *check.C) {
234 var stdout, stderr bytes.Buffer
235 // Run costanalyzer with 2 container request uuids
236 exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedDiagnosticsContainerRequest1UUID, "-uuid", arvadostest.CompletedDiagnosticsContainerRequest2UUID}, &bytes.Buffer{}, &stdout, &stderr)
237 c.Check(exitcode, check.Equals, 0)
238 c.Assert(stdout.String(), check.Matches, "(?ms).*supplied uuids in .*")
240 uuidReport, err := ioutil.ReadFile("results/" + arvadostest.CompletedDiagnosticsContainerRequest1UUID + ".csv")
241 c.Assert(err, check.IsNil)
242 c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,0.00914539")
244 uuidReport2, err := ioutil.ReadFile("results/" + arvadostest.CompletedDiagnosticsContainerRequest2UUID + ".csv")
245 c.Assert(err, check.IsNil)
246 c.Check(string(uuidReport2), check.Matches, "(?ms).*TOTAL,,,,,,,,,0.00586435")
248 re := regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
249 matches := re.FindStringSubmatch(stdout.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
251 aggregateCostReport, err := ioutil.ReadFile(matches[1])
252 c.Assert(err, check.IsNil)
254 c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,0.01490377")