[ARVADOS] updated: 2.1.0-185-g6f5431413

Git user git at public.arvados.org
Sun Dec 6 15:54:38 UTC 2020


Summary of changes:
 lib/costanalyzer/costanalyzer.go      | 6 ++++++
 lib/costanalyzer/costanalyzer_test.go | 9 +++++++++
 2 files changed, 15 insertions(+)

  discards  64a9a6663b446225fb9916e68c5aada55eaedaea (commit)
  discards  bbb12c3c1600b88c3d5bc9852883c39935f6a70a (commit)
       via  6f5431413448f52f3ae5c88553b7f7ee1532b9fd (commit)
       via  641876e22db7b51231415574366c76acd39794a5 (commit)
       via  1f773811a85c564bec4606d7ad05e7805fa41f22 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (64a9a6663b446225fb9916e68c5aada55eaedaea)
            \
             N -- N -- N (6f5431413448f52f3ae5c88553b7f7ee1532b9fd)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 6f5431413448f52f3ae5c88553b7f7ee1532b9fd
Author: Ward Vandewege <ward at curii.com>
Date:   Sun Dec 6 10:54:11 2020 -0500

    17187: costanalyzer: print the total from the aggregate cost accounting
           across all uuids to stdout.
    
    Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <ward at curii.com>

diff --git a/lib/costanalyzer/costanalyzer.go b/lib/costanalyzer/costanalyzer.go
index 01a9d9fdb..bca23b153 100644
--- a/lib/costanalyzer/costanalyzer.go
+++ b/lib/costanalyzer/costanalyzer.go
@@ -94,6 +94,9 @@ Usage:
 	In order to get the data for the uuids supplied, the ARVADOS_API_HOST and
 	ARVADOS_API_TOKEN environment variables must be set.
 
+	This program prints the total dollar amount from the aggregate cost
+	accounting across all provided uuids on stdout.
+
 Options:
 `, prog)
 		flags.PrintDefaults()
@@ -548,5 +551,8 @@ func costanalyzer(prog string, args []string, loader *config.Loader, logger *log
 		return
 	}
 	logger.Infof("Aggregate cost accounting for all supplied uuids in %s\n", aFile)
+	// Output the total dollar amount on stdout
+	fmt.Fprintf(stdout, "%s\n", strconv.FormatFloat(total, 'f', 8, 64))
+
 	return
 }
diff --git a/lib/costanalyzer/costanalyzer_test.go b/lib/costanalyzer/costanalyzer_test.go
index 36421dc7f..48e7733e1 100644
--- a/lib/costanalyzer/costanalyzer_test.go
+++ b/lib/costanalyzer/costanalyzer_test.go
@@ -290,6 +290,12 @@ func (*Suite) TestMultipleContainerRequestUUIDWithReuse(c *check.C) {
 	c.Check(exitcode, check.Equals, 0)
 	c.Assert(stderr.String(), check.Matches, "(?ms).*supplied uuids in .*")
 
+	// Check that the total amount was printed to stdout
+	c.Check(stdout.String(), check.Matches, "0.01492030\n")
+
+	stdout.Truncate(0)
+	stderr.Truncate(0)
+
 	// Run costanalyzer with 2 container request uuids
 	exitcode = Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedDiagnosticsContainerRequest1UUID, "-uuid", arvadostest.CompletedDiagnosticsContainerRequest2UUID, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
 	c.Check(exitcode, check.Equals, 0)

commit 641876e22db7b51231415574366c76acd39794a5
Author: Ward Vandewege <ward at curii.com>
Date:   Sun Dec 6 10:26:39 2020 -0500

    17187: costanalyzer: allow specifying multiple comma-separated uuids via
           one -uuid argument
    
    Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <ward at curii.com>

diff --git a/lib/costanalyzer/costanalyzer.go b/lib/costanalyzer/costanalyzer.go
index 75cbdc037..01a9d9fdb 100644
--- a/lib/costanalyzer/costanalyzer.go
+++ b/lib/costanalyzer/costanalyzer.go
@@ -44,7 +44,9 @@ func (i *arrayFlags) String() string {
 }
 
 func (i *arrayFlags) Set(value string) error {
-	*i = append(*i, value)
+	for _, s := range strings.Split(value, ",") {
+		*i = append(*i, s)
+	}
 	return nil
 }
 
@@ -98,7 +100,7 @@ Options:
 	}
 	loglevel := flags.String("log-level", "info", "logging `level` (debug, info, ...)")
 	flags.StringVar(&resultsDir, "output", "", "output `directory` for the CSV reports (required)")
-	flags.Var(&uuids, "uuid", "Toplevel `project or container request` uuid. May be specified more than once. (required)")
+	flags.Var(&uuids, "uuid", "object uuid. May be specified more than once. Also accepts a comma separated list of uuids (required)")
 	flags.BoolVar(&cache, "cache", true, "create and use a local disk cache of Arvados objects")
 	err = flags.Parse(args)
 	if err == flag.ErrHelp {
diff --git a/lib/costanalyzer/costanalyzer_test.go b/lib/costanalyzer/costanalyzer_test.go
index 4f0f64dae..36421dc7f 100644
--- a/lib/costanalyzer/costanalyzer_test.go
+++ b/lib/costanalyzer/costanalyzer_test.go
@@ -285,8 +285,13 @@ func (*Suite) TestDoubleContainerRequestUUID(c *check.C) {
 
 func (*Suite) TestMultipleContainerRequestUUIDWithReuse(c *check.C) {
 	var stdout, stderr bytes.Buffer
+	// Run costanalyzer with 2 container request uuids, as one comma separated -uuid argument
+	exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedDiagnosticsContainerRequest1UUID + "," + arvadostest.CompletedDiagnosticsContainerRequest2UUID, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
+	c.Check(exitcode, check.Equals, 0)
+	c.Assert(stderr.String(), check.Matches, "(?ms).*supplied uuids in .*")
+
 	// Run costanalyzer with 2 container request uuids
-	exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedDiagnosticsContainerRequest1UUID, "-uuid", arvadostest.CompletedDiagnosticsContainerRequest2UUID, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
+	exitcode = Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.CompletedDiagnosticsContainerRequest1UUID, "-uuid", arvadostest.CompletedDiagnosticsContainerRequest2UUID, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
 	c.Check(exitcode, check.Equals, 0)
 	c.Assert(stderr.String(), check.Matches, "(?ms).*supplied uuids in .*")
 

commit 1f773811a85c564bec4606d7ad05e7805fa41f22
Author: Ward Vandewege <ward at curii.com>
Date:   Sat Dec 5 16:37:00 2020 -0500

    17187: costanalyzer: add support for collection uuids.
    
    Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <ward at curii.com>

diff --git a/lib/costanalyzer/costanalyzer.go b/lib/costanalyzer/costanalyzer.go
index 4284542b8..75cbdc037 100644
--- a/lib/costanalyzer/costanalyzer.go
+++ b/lib/costanalyzer/costanalyzer.go
@@ -62,12 +62,18 @@ Usage:
 	each container.
 
 	When supplied with the uuid of a container request, it will calculate the
-	cost of that container request and all its children. When suplied with a
-	project uuid or when supplied with multiple container request uuids, it will
-	create a CSV report for each supplied uuid, as well as a CSV file with
-	aggregate cost accounting for all supplied uuids. The aggregate cost report
-	takes container reuse into account: if a container was reused between several
-	container requests, its cost will only be counted once.
+	cost of that container request and all its children.
+
+	When supplied with the uuid of a collection, it will see if there is a
+	container_request uuid in the properties of the collection, and if so, it
+	will calculate the cost of that container request and all its children.
+
+	When supplied with a project uuid or when supplied with multiple container
+	request or collection uuids, it will create a CSV report for each supplied
+	uuid, as well as a CSV file with aggregate cost accounting for all supplied
+	uuids. The aggregate cost report takes container reuse into account: if a
+	container was reused between several container requests, its cost will only
+	be counted once.
 
 	To get the node costs, the progam queries the Arvados API for current cost
 	data for each node type used. This means that the reported cost always
@@ -180,8 +186,8 @@ func addContainerLine(logger *logrus.Logger, node nodeInfo, cr arvados.Container
 
 func loadCachedObject(logger *logrus.Logger, file string, uuid string, object interface{}) (reload bool) {
 	reload = true
-	if strings.Contains(uuid, "-j7d0g-") {
-		// We do not cache projects, they have no final state
+	if strings.Contains(uuid, "-j7d0g-") || strings.Contains(uuid, "-4zz18-") {
+		// We do not cache projects or collections, they have no final state
 		return
 	}
 	// See if we have a cached copy of this object
@@ -251,6 +257,8 @@ func loadObject(logger *logrus.Logger, ac *arvados.Client, path string, uuid str
 		err = ac.RequestAndDecode(&object, "GET", "arvados/v1/container_requests/"+uuid, nil, nil)
 	} else if strings.Contains(uuid, "-dz642-") {
 		err = ac.RequestAndDecode(&object, "GET", "arvados/v1/containers/"+uuid, nil, nil)
+	} else if strings.Contains(uuid, "-4zz18-") {
+		err = ac.RequestAndDecode(&object, "GET", "arvados/v1/collections/"+uuid, nil, nil)
 	} else {
 		err = fmt.Errorf("unsupported object type with UUID %q:\n  %s", uuid, err)
 		return
@@ -309,7 +317,6 @@ func getNode(arv *arvadosclient.ArvadosClient, ac *arvados.Client, kc *keepclien
 }
 
 func handleProject(logger *logrus.Logger, uuid string, arv *arvadosclient.ArvadosClient, ac *arvados.Client, kc *keepclient.KeepClient, resultsDir string, cache bool) (cost map[string]float64, err error) {
-
 	cost = make(map[string]float64)
 
 	var project arvados.Group
@@ -366,9 +373,24 @@ func generateCrCsv(logger *logrus.Logger, uuid string, arv *arvadosclient.Arvado
 	var tmpTotalCost float64
 	var totalCost float64
 
+	var crUUID = uuid
+	if strings.Contains(uuid, "-4zz18-") {
+		// This is a collection, find the associated container request (if any)
+		var c arvados.Collection
+		err = loadObject(logger, ac, uuid, uuid, cache, &c)
+		if err != nil {
+			return nil, fmt.Errorf("error loading collection object %s: %s", uuid, err)
+		}
+		value, ok := c.Properties["container_request"]
+		if !ok {
+			return nil, fmt.Errorf("error: collection %s does not have a 'container_request' property", uuid)
+		}
+		crUUID = value.(string)
+	}
+
 	// This is a container request, find the container
 	var cr arvados.ContainerRequest
-	err = loadObject(logger, ac, uuid, uuid, cache, &cr)
+	err = loadObject(logger, ac, crUUID, crUUID, cache, &cr)
 	if err != nil {
 		return nil, fmt.Errorf("error loading cr object %s: %s", uuid, err)
 	}
@@ -474,12 +496,12 @@ func costanalyzer(prog string, args []string, loader *config.Loader, logger *log
 			for k, v := range cost {
 				cost[k] = v
 			}
-		} else if strings.Contains(uuid, "-xvhdp-") {
+		} else if strings.Contains(uuid, "-xvhdp-") || strings.Contains(uuid, "-4zz18-") {
 			// This is a container request
 			var crCsv map[string]float64
 			crCsv, err = generateCrCsv(logger, uuid, arv, ac, kc, resultsDir, cache)
 			if err != nil {
-				err = fmt.Errorf("Error generating container_request CSV for uuid %s: %s", uuid, err.Error())
+				err = fmt.Errorf("Error generating CSV for uuid %s: %s", uuid, err.Error())
 				exitcode = 2
 				return
 			}
diff --git a/lib/costanalyzer/costanalyzer_test.go b/lib/costanalyzer/costanalyzer_test.go
index 4fab93bf4..4f0f64dae 100644
--- a/lib/costanalyzer/costanalyzer_test.go
+++ b/lib/costanalyzer/costanalyzer_test.go
@@ -177,6 +177,48 @@ func (*Suite) TestContainerRequestUUID(c *check.C) {
 	c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,7.01302889")
 }
 
+func (*Suite) TestCollectionUUID(c *check.C) {
+	var stdout, stderr bytes.Buffer
+
+	// Run costanalyzer with 1 collection uuid, without 'container_request' property
+	exitcode := Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.FooCollection, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
+	c.Check(exitcode, check.Equals, 2)
+	c.Assert(stderr.String(), check.Matches, "(?ms).*does not have a 'container_request' property.*")
+
+	// Update the collection, attach a 'container_request' property
+	ac := arvados.NewClientFromEnv()
+	var coll arvados.Collection
+
+	// Update collection record
+	err := ac.RequestAndDecode(&coll, "PUT", "arvados/v1/collections/"+arvadostest.FooCollection, nil, map[string]interface{}{
+		"collection": map[string]interface{}{
+			"properties": map[string]interface{}{
+				"container_request": arvadostest.CompletedContainerRequestUUID,
+			},
+		},
+	})
+	c.Assert(err, check.IsNil)
+
+	stdout.Truncate(0)
+	stderr.Truncate(0)
+
+	// Run costanalyzer with 1 collection uuid
+	exitcode = Command.RunCommand("costanalyzer.test", []string{"-uuid", arvadostest.FooCollection, "-output", "results"}, &bytes.Buffer{}, &stdout, &stderr)
+	c.Check(exitcode, check.Equals, 0)
+	c.Assert(stderr.String(), check.Matches, "(?ms).*supplied uuids in .*")
+
+	uuidReport, err := ioutil.ReadFile("results/" + arvadostest.CompletedContainerRequestUUID + ".csv")
+	c.Assert(err, check.IsNil)
+	c.Check(string(uuidReport), check.Matches, "(?ms).*TOTAL,,,,,,,,,7.01302889")
+	re := regexp.MustCompile(`(?ms).*supplied uuids in (.*?)\n`)
+	matches := re.FindStringSubmatch(stderr.String()) // matches[1] contains a string like 'results/2020-11-02-18-57-45-aggregate-costaccounting.csv'
+
+	aggregateCostReport, err := ioutil.ReadFile(matches[1])
+	c.Assert(err, check.IsNil)
+
+	c.Check(string(aggregateCostReport), check.Matches, "(?ms).*TOTAL,7.01302889")
+}
+
 func (*Suite) TestDoubleContainerRequestUUID(c *check.C) {
 	var stdout, stderr bytes.Buffer
 	// Run costanalyzer with 2 container request uuids

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list