[ARVADOS] updated: 1.3.0-3258-g8d62d0283
Git user
git at public.arvados.org
Sat Oct 31 01:27:25 UTC 2020
Summary of changes:
services/api/test/fixtures/collections.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
discards 78d04ef55cc257a345ad660618e163ae5639d60d (commit)
discards 944aa20b963f960d317e1c57b0687d2b77adde8c (commit)
via 8d62d02834f289b30adafdeeb824ac03da5ff745 (commit)
via 15aa3f9e8de69cb638bad461628f115f8a5bc276 (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 (78d04ef55cc257a345ad660618e163ae5639d60d)
\
N -- N -- N (8d62d02834f289b30adafdeeb824ac03da5ff745)
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 8d62d02834f289b30adafdeeb824ac03da5ff745
Author: Ward Vandewege <ward at curii.com>
Date: Sat Oct 3 13:58:50 2020 -0400
16950: add the costanalyzer to arvados-client.
Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <ward at curii.com>
diff --git a/cmd/arvados-client/cmd.go b/cmd/arvados-client/cmd.go
index bcc3dda09..47fcd5ad7 100644
--- a/cmd/arvados-client/cmd.go
+++ b/cmd/arvados-client/cmd.go
@@ -9,6 +9,7 @@ import (
"git.arvados.org/arvados.git/lib/cli"
"git.arvados.org/arvados.git/lib/cmd"
+ "git.arvados.org/arvados.git/lib/costanalyzer"
"git.arvados.org/arvados.git/lib/deduplicationreport"
"git.arvados.org/arvados.git/lib/mount"
)
@@ -55,6 +56,7 @@ var (
"mount": mount.Command,
"deduplication-report": deduplicationreport.Command,
+ "costanalyzer": costanalyzer.Command,
})
)
diff --git a/lib/costanalyzer/command.go b/lib/costanalyzer/command.go
new file mode 100644
index 000000000..3cca16ea0
--- /dev/null
+++ b/lib/costanalyzer/command.go
@@ -0,0 +1,43 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package costanalyzer
+
+import (
+ "io"
+
+ "git.arvados.org/arvados.git/lib/config"
+ "git.arvados.org/arvados.git/sdk/go/ctxlog"
+ "github.com/sirupsen/logrus"
+)
+
+var Command command
+
+type command struct{}
+
+type NoPrefixFormatter struct{}
+
+func (f *NoPrefixFormatter) Format(entry *logrus.Entry) ([]byte, error) {
+ return []byte(entry.Message), nil
+}
+
+// RunCommand implements the subcommand "deduplication-report <collection> <collection> ..."
+func (command) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
+ var err error
+ logger := ctxlog.New(stderr, "text", "info")
+ defer func() {
+ if err != nil {
+ logger.WithError(err).Error("fatal")
+ }
+ }()
+
+ logger.SetFormatter(new(NoPrefixFormatter))
+
+ loader := config.NewLoader(stdin, logger)
+ loader.SkipLegacy = true
+
+ exitcode := costanalyzer(prog, args, loader, logger, stdout, stderr)
+
+ return exitcode
+}
diff --git a/lib/costanalyzer/costanalyzer.go b/lib/costanalyzer/costanalyzer.go
new file mode 100644
index 000000000..d754e8875
--- /dev/null
+++ b/lib/costanalyzer/costanalyzer.go
@@ -0,0 +1,559 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+package costanalyzer
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "flag"
+ "fmt"
+ "git.arvados.org/arvados.git/lib/config"
+ "git.arvados.org/arvados.git/sdk/go/arvados"
+ "git.arvados.org/arvados.git/sdk/go/arvadosclient"
+ "git.arvados.org/arvados.git/sdk/go/keepclient"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/sirupsen/logrus"
+)
+
+// Dict is a helper type so we don't have to write out 'map[string]interface{}' every time.
+type Dict map[string]interface{}
+
+// LegacyNodeInfo is a struct for records created by Arvados Node Manager (Arvados <= 1.4.3)
+// Example:
+// {
+// "total_cpu_cores":2,
+// "total_scratch_mb":33770,
+// "cloud_node":
+// {
+// "price":0.1,
+// "size":"m4.large"
+// },
+// "total_ram_mb":7986
+// }
+type LegacyNodeInfo struct {
+ CPUCores int64 `json:"total_cpu_cores"`
+ ScratchMb int64 `json:"total_scratch_mb"`
+ RAMMb int64 `json:"total_ram_mb"`
+ CloudNode LegacyCloudNode `json:"cloud_node"`
+}
+
+// LegacyCloudNode is a struct for records created by Arvados Node Manager (Arvados <= 1.4.3)
+type LegacyCloudNode struct {
+ Price float64 `json:"price"`
+ Size string `json:"size"`
+}
+
+// Node is a struct for records created by Arvados Dispatch Cloud (Arvados >= 2.0.0)
+// Example:
+// {
+// "Name": "Standard_D1_v2",
+// "ProviderType": "Standard_D1_v2",
+// "VCPUs": 1,
+// "RAM": 3584000000,
+// "Scratch": 50000000000,
+// "IncludedScratch": 50000000000,
+// "AddedScratch": 0,
+// "Price": 0.057,
+// "Preemptible": false
+//}
+type Node struct {
+ VCPUs int64
+ Scratch int64
+ RAM int64
+ Price float64
+ Name string
+ ProviderType string
+ Preemptible bool
+}
+
+type arrayFlags []string
+
+func (i *arrayFlags) String() string {
+ return ""
+}
+
+func (i *arrayFlags) Set(value string) error {
+ *i = append(*i, value)
+ return nil
+}
+
+func parseFlags(prog string, args []string, loader *config.Loader, logger *logrus.Logger, stderr io.Writer) (exitCode int, uuids arrayFlags, resultsDir string) {
+ flags := flag.NewFlagSet("", flag.ContinueOnError)
+ flags.SetOutput(stderr)
+ flags.Usage = func() {
+ fmt.Fprintf(flags.Output(), `
+Usage:
+ %s [options ...]
+
+ This program analyzes the cost of Arvados container requests. For each uuid
+ supplied, it creates a CSV report that lists all the containers used to
+ fulfill the container request, together with the machine type and cost of
+ 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.
+
+ 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
+ reflects the cost data as currently defined in the Arvados API configuration
+ file.
+
+ Caveats:
+ - the Arvados API configuration cost data may be out of sync with the cloud
+ provider.
+ - when generating reports for older container requests, the cost data in the
+ Arvados API configuration file may have changed since the container request
+ was fulfilled.
+
+ In order to get the data for the uuids supplied, the ARVADOS_API_HOST and
+ ARVADOS_API_TOKEN environment variables must be set.
+
+Options:
+`, prog)
+ flags.PrintDefaults()
+ }
+ loglevel := flags.String("log-level", "info", "logging level (debug, info, ...)")
+ resultsDir = *flags.String("output", "results", "output directory for the CSV reports")
+ flags.Var(&uuids, "uuid", "Toplevel project or container request uuid. May be specified more than once.")
+ err := flags.Parse(args)
+ if err == flag.ErrHelp {
+ exitCode = 0
+ return
+ } else if err != nil {
+ exitCode = 2
+ return
+ }
+
+ if len(uuids) < 1 {
+ logger.Errorf("Error: no uuid(s) provided")
+ flags.Usage()
+ exitCode = 2
+ return
+ }
+
+ lvl, err := logrus.ParseLevel(*loglevel)
+ if err != nil {
+ exitCode = 2
+ return
+ }
+ logger.SetLevel(lvl)
+ return
+}
+
+func ensureDirectory(logger *logrus.Logger, dir string) {
+ statData, err := os.Stat(dir)
+ if os.IsNotExist(err) {
+ err = os.MkdirAll(dir, 0700)
+ if err != nil {
+ logger.Errorf("Error creating directory %s: %s\n", dir, err.Error())
+ os.Exit(1)
+ }
+ } else {
+ if !statData.IsDir() {
+ logger.Errorf("The path %s is not a directory\n", dir)
+ os.Exit(1)
+ }
+ }
+}
+
+func addContainerLine(logger *logrus.Logger, node interface{}, cr Dict, container Dict) (csv string, cost float64) {
+ csv = cr["uuid"].(string) + ","
+ csv += cr["name"].(string) + ","
+ csv += container["uuid"].(string) + ","
+ csv += container["state"].(string) + ","
+ if container["started_at"] != nil {
+ csv += container["started_at"].(string) + ","
+ } else {
+ csv += ","
+ }
+
+ var delta time.Duration
+ if container["finished_at"] != nil {
+ csv += container["finished_at"].(string) + ","
+ finishedTimestamp, err := time.Parse("2006-01-02T15:04:05.000000000Z", container["finished_at"].(string))
+ if err != nil {
+ fmt.Println(err)
+ }
+ startedTimestamp, err := time.Parse("2006-01-02T15:04:05.000000000Z", container["started_at"].(string))
+ if err != nil {
+ fmt.Println(err)
+ }
+ delta = finishedTimestamp.Sub(startedTimestamp)
+ csv += strconv.FormatFloat(delta.Seconds(), 'f', 0, 64) + ","
+ } else {
+ csv += ",,"
+ }
+ var price float64
+ var size string
+ switch n := node.(type) {
+ case Node:
+ price = n.Price
+ size = n.ProviderType
+ case LegacyNodeInfo:
+ price = n.CloudNode.Price
+ size = n.CloudNode.Size
+ default:
+ logger.Warn("WARNING: unknown node type found!")
+ }
+ cost = delta.Seconds() / 3600 * price
+ csv += size + "," + strconv.FormatFloat(price, 'f', 8, 64) + "," + strconv.FormatFloat(cost, 'f', 8, 64) + "\n"
+ return
+}
+
+func loadCachedObject(logger *logrus.Logger, file string, uuid string) (reload bool, object Dict) {
+ reload = true
+ // See if we have a cached copy of this object
+ if _, err := os.Stat(file); err == nil {
+ data, err := ioutil.ReadFile(file)
+ if err != nil {
+ logger.Errorf("error reading %q: %s", file, err)
+ return
+ }
+ err = json.Unmarshal(data, &object)
+ if err != nil {
+ logger.Errorf("failed to unmarshal json: %s: %s", data, err)
+ return
+ }
+
+ // See if it is in a final state, if that makes sense
+ // Projects (j7d0g) do not have state so they should always be reloaded
+ if !strings.Contains(uuid, "-j7d0g-") {
+ if object["state"].(string) == "Complete" || object["state"].(string) == "Failed" {
+ reload = false
+ logger.Debugf("Loaded object %s from local cache (%s)\n", uuid, file)
+ return
+ }
+ }
+ }
+ return
+}
+
+// Load an Arvados object.
+func loadObject(logger *logrus.Logger, arv *arvadosclient.ArvadosClient, path string, uuid string) (object Dict) {
+
+ ensureDirectory(logger, path)
+
+ file := path + "/" + uuid + ".json"
+
+ var reload bool
+ reload, object = loadCachedObject(logger, file, uuid)
+
+ if reload {
+ var err error
+ if strings.Contains(uuid, "-d1hrv-") {
+ err = arv.Get("pipeline_instances", uuid, nil, &object)
+ } else if strings.Contains(uuid, "-j7d0g-") {
+ err = arv.Get("groups", uuid, nil, &object)
+ } else if strings.Contains(uuid, "-xvhdp-") {
+ err = arv.Get("container_requests", uuid, nil, &object)
+ } else if strings.Contains(uuid, "-dz642-") {
+ err = arv.Get("containers", uuid, nil, &object)
+ } else {
+ err = arv.Get("jobs", uuid, nil, &object)
+ }
+ if err != nil {
+ logger.Errorf("Error loading object with UUID %q:\n %s\n", uuid, err)
+ os.Exit(1)
+ }
+ encoded, err := json.MarshalIndent(object, "", " ")
+ if err != nil {
+ logger.Errorf("Error marshaling object with UUID %q:\n %s\n", uuid, err)
+ os.Exit(1)
+ }
+ err = ioutil.WriteFile(file, encoded, 0644)
+ if err != nil {
+ logger.Errorf("Error writing file %s:\n %s\n", file, err)
+ os.Exit(1)
+ }
+ }
+ return
+}
+
+func getNode(logger *logrus.Logger, arv *arvadosclient.ArvadosClient, arv2 *arvados.Client, kc *keepclient.KeepClient, itemMap Dict) (node interface{}, err error) {
+ if _, ok := itemMap["log_uuid"]; ok {
+ if itemMap["log_uuid"] == nil {
+ err = errors.New("No log collection")
+ return
+ }
+
+ var collection arvados.Collection
+ err = arv.Get("collections", itemMap["log_uuid"].(string), nil, &collection)
+ if err != nil {
+ logger.Errorf("error getting collection: %s\n", err)
+ return
+ }
+
+ var fs arvados.CollectionFileSystem
+ fs, err = collection.FileSystem(arv2, kc)
+ if err != nil {
+ logger.Errorf("error opening collection as filesystem: %s\n", err)
+ return
+ }
+ var f http.File
+ f, err = fs.Open("node.json")
+ if err != nil {
+ logger.Errorf("error opening file in collection: %s\n", err)
+ return
+ }
+
+ var nodeDict Dict
+ // TODO: checkout io (ioutil?) readall function
+ buf := new(bytes.Buffer)
+ _, err = buf.ReadFrom(f)
+ if err != nil {
+ logger.Errorf("error reading %q: %s\n", f, err)
+ return
+ }
+ contents := buf.String()
+ f.Close()
+
+ err = json.Unmarshal([]byte(contents), &nodeDict)
+ if err != nil {
+ logger.Errorf("error unmarshalling: %s\n", err)
+ return
+ }
+ if val, ok := nodeDict["properties"]; ok {
+ var encoded []byte
+ encoded, err = json.MarshalIndent(val, "", " ")
+ if err != nil {
+ logger.Errorf("error marshalling: %s\n", err)
+ return
+ }
+ // node is type LegacyNodeInfo
+ var newNode LegacyNodeInfo
+ err = json.Unmarshal(encoded, &newNode)
+ if err != nil {
+ logger.Errorf("error unmarshalling: %s\n", err)
+ return
+ }
+ node = newNode
+ } else {
+ // node is type Node
+ var newNode Node
+ err = json.Unmarshal([]byte(contents), &newNode)
+ if err != nil {
+ logger.Errorf("error unmarshalling: %s\n", err)
+ return
+ }
+ node = newNode
+ }
+ }
+ return
+}
+
+func handleProject(logger *logrus.Logger, uuid string, arv *arvadosclient.ArvadosClient, arv2 *arvados.Client, kc *keepclient.KeepClient, resultsDir string) (cost map[string]float64) {
+
+ cost = make(map[string]float64)
+
+ project := loadObject(logger, arv, resultsDir+"/"+uuid, uuid)
+
+ // arv -f uuid container_request list --filters '[["owner_uuid","=","<someuuid>"],["requesting_container_uuid","=",null]]'
+
+ // Now find all container requests that have the container we found above as requesting_container_uuid
+ var childCrs map[string]interface{}
+ filterset := []arvados.Filter{
+ {
+ Attr: "owner_uuid",
+ Operator: "=",
+ Operand: project["uuid"].(string),
+ },
+ {
+ Attr: "requesting_container_uuid",
+ Operator: "=",
+ Operand: nil,
+ },
+ }
+ err := arv.List("container_requests", arvadosclient.Dict{"filters": filterset, "limit": 10000}, &childCrs)
+ if err != nil {
+ logger.Fatalf("Error querying container_requests: %s\n", err.Error())
+ }
+ if value, ok := childCrs["items"]; ok {
+ logger.Infof("Collecting top level container requests in project %s\n", uuid)
+ items := value.([]interface{})
+ for _, item := range items {
+ itemMap := item.(map[string]interface{})
+ for k, v := range generateCrCsv(logger, itemMap["uuid"].(string), arv, arv2, kc, resultsDir) {
+ cost[k] = v
+ }
+ }
+ } else {
+ logger.Infof("No top level container requests found in project %s\n", uuid)
+ }
+ return
+}
+
+func generateCrCsv(logger *logrus.Logger, uuid string, arv *arvadosclient.ArvadosClient, arv2 *arvados.Client, kc *keepclient.KeepClient, resultsDir string) (cost map[string]float64) {
+
+ cost = make(map[string]float64)
+
+ csv := "CR UUID,CR name,Container UUID,State,Started At,Finished At,Duration in seconds,Compute node type,Hourly node cost,Total cost\n"
+ var tmpCsv string
+ var tmpTotalCost float64
+ var totalCost float64
+
+ // This is a container request, find the container
+ cr := loadObject(logger, arv, resultsDir+"/"+uuid, uuid)
+ container := loadObject(logger, arv, resultsDir+"/"+uuid, cr["container_uuid"].(string))
+
+ topNode, err := getNode(logger, arv, arv2, kc, cr)
+ if err != nil {
+ log.Fatalf("error getting node: %s", err)
+ }
+ tmpCsv, totalCost = addContainerLine(logger, topNode, cr, container)
+ csv += tmpCsv
+ totalCost += tmpTotalCost
+
+ cost[container["uuid"].(string)] = totalCost
+
+ // Now find all container requests that have the container we found above as requesting_container_uuid
+ var childCrs map[string]interface{}
+ filterset := []arvados.Filter{
+ {
+ Attr: "requesting_container_uuid",
+ Operator: "=",
+ Operand: container["uuid"].(string),
+ }}
+ err = arv.List("container_requests", arvadosclient.Dict{"filters": filterset, "limit": 10000}, &childCrs)
+ if err != nil {
+ log.Fatal("error querying container_requests", err.Error())
+ }
+ if value, ok := childCrs["items"]; ok {
+ logger.Infof("Collecting child containers for container request %s", uuid)
+ items := value.([]interface{})
+ for _, item := range items {
+ logger.Info(".")
+ itemMap := item.(map[string]interface{})
+ node, _ := getNode(logger, arv, arv2, kc, itemMap)
+ logger.Debug("\nChild container: " + itemMap["container_uuid"].(string) + "\n")
+ c2 := loadObject(logger, arv, resultsDir+"/"+uuid, itemMap["container_uuid"].(string))
+ tmpCsv, tmpTotalCost = addContainerLine(logger, node, itemMap, c2)
+ cost[itemMap["container_uuid"].(string)] = tmpTotalCost
+ csv += tmpCsv
+ totalCost += tmpTotalCost
+ }
+ }
+ logger.Info(" done\n")
+
+ csv += "TOTAL,,,,,,,,," + strconv.FormatFloat(totalCost, 'f', 8, 64) + "\n"
+
+ // Write the resulting CSV file
+ fName := resultsDir + "/" + uuid + ".csv"
+ err = ioutil.WriteFile(fName, []byte(csv), 0644)
+ if err != nil {
+ logger.Errorf("Error writing file with path %s: %s\n", fName, err.Error())
+ os.Exit(1)
+ }
+
+ return
+}
+
+func costanalyzer(prog string, args []string, loader *config.Loader, logger *logrus.Logger, stdout, stderr io.Writer) (exitcode int) {
+ exitcode, uuids, resultsDir := parseFlags(prog, args, loader, logger, stderr)
+ if exitcode != 0 {
+ return
+ }
+
+ ensureDirectory(logger, resultsDir)
+
+ // Arvados Client setup
+ arv, err := arvadosclient.MakeArvadosClient()
+ if err != nil {
+ logger.Errorf("error creating Arvados object: %s", err)
+ os.Exit(1)
+ }
+ kc, err := keepclient.MakeKeepClient(arv)
+ if err != nil {
+ logger.Errorf("error creating Keep object: %s", err)
+ os.Exit(1)
+ }
+
+ arv2 := arvados.NewClientFromEnv()
+
+ cost := make(map[string]float64)
+
+ for _, uuid := range uuids {
+ //csv := "CR UUID,CR name,Container UUID,State,Started At,Finished At,Duration in seconds,Compute node type,Hourly node cost,Total cost\n"
+
+ if strings.Contains(uuid, "-d1hrv-") {
+ // This is a pipeline instance, not a job! Find the cwl-runner job.
+ pi := loadObject(logger, arv, resultsDir+"/"+uuid, uuid)
+ for _, v := range pi["components"].(map[string]interface{}) {
+ x := v.(map[string]interface{})
+ y := x["job"].(map[string]interface{})
+ uuid = y["uuid"].(string)
+ }
+ }
+
+ // for projects:
+ // arv -f uuid container_request list --filters '[["owner_uuid","=","<someuuid>"],["requesting_container_uuid","=",null]]'
+
+ if strings.Contains(uuid, "-j7d0g-") {
+ // This is a project (group)
+ for k, v := range handleProject(logger, uuid, arv, arv2, kc, resultsDir) {
+ cost[k] = v
+ }
+ } else if strings.Contains(uuid, "-xvhdp-") {
+ // This is a container request
+ for k, v := range generateCrCsv(logger, uuid, arv, arv2, kc, resultsDir) {
+ cost[k] = v
+ }
+ } else if strings.Contains(uuid, "-tpzed-") {
+ // This is a user. The "Home" project for a user is not a real project.
+ // It is identified by the user uuid. As such, cost analysis for the
+ // "Home" project is not supported by this program.
+ logger.Errorf("Cost analysis is not supported for the 'Home' project: %s", uuid)
+ }
+ }
+
+ logger.Info("\n")
+ for k := range cost {
+ logger.Infof("Uuid report in %s/%s.csv\n", resultsDir, k)
+ }
+
+ if len(cost) == 0 {
+ logger.Info("Nothing to do!\n")
+ os.Exit(0)
+ }
+
+ var csv string
+
+ csv = "# Aggregate cost accounting for uuids:\n"
+ for _, uuid := range uuids {
+ csv += "# " + uuid + "\n"
+ }
+
+ var total float64
+ for k, v := range cost {
+ csv += k + "," + strconv.FormatFloat(v, 'f', 8, 64) + "\n"
+ total += v
+ }
+
+ csv += "TOTAL," + strconv.FormatFloat(total, 'f', 8, 64) + "\n"
+
+ // Write the resulting CSV file
+ aFile := resultsDir + "/" + time.Now().Format("2006-01-02-15-04-05") + "-aggregate-costaccounting.csv"
+ err = ioutil.WriteFile(aFile, []byte(csv), 0644)
+ if err != nil {
+ logger.Errorf("Error writing file with path %s: %s\n", aFile, err.Error())
+ os.Exit(1)
+ } else {
+ logger.Infof("\nAggregate cost accounting for all supplied uuids in %s\n", aFile)
+ }
+ return
+}
commit 15aa3f9e8de69cb638bad461628f115f8a5bc276
Author: Ward Vandewege <ward at curii.com>
Date: Fri Oct 30 16:29:40 2020 -0400
16950: a few cleanups for our container request fixtures: attach a real
log collection, and define CompletedContainerRequestUUID in
arvadostest (go).
Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <ward at curii.com>
diff --git a/sdk/go/arvadostest/fixtures.go b/sdk/go/arvadostest/fixtures.go
index 5677f4dec..9049c73c4 100644
--- a/sdk/go/arvadostest/fixtures.go
+++ b/sdk/go/arvadostest/fixtures.go
@@ -44,7 +44,8 @@ const (
RunningContainerUUID = "zzzzz-dz642-runningcontainr"
- CompletedContainerUUID = "zzzzz-dz642-compltcontainer"
+ CompletedContainerUUID = "zzzzz-dz642-compltcontainer"
+ CompletedContainerRequestUUID = "zzzzz-xvhdp-cr4completedctr"
ArvadosRepoUUID = "zzzzz-s0uqq-arvadosrepo0123"
ArvadosRepoName = "arvados"
@@ -73,6 +74,8 @@ const (
TestVMUUID = "zzzzz-2x53u-382brsig8rp3064"
CollectionWithUniqueWordsUUID = "zzzzz-4zz18-mnt690klmb51aud"
+
+ LogCollectionUUID = "zzzzz-4zz18-logcollection01"
)
// PathologicalManifest : A valid manifest designed to test
diff --git a/services/api/test/fixtures/collections.yml b/services/api/test/fixtures/collections.yml
index a16ee8763..2243d6a44 100644
--- a/services/api/test/fixtures/collections.yml
+++ b/services/api/test/fixtures/collections.yml
@@ -1031,6 +1031,18 @@ collection_with_uri_prop:
properties:
"http://schema.org/example": "value1"
+log_collection:
+ uuid: zzzzz-4zz18-logcollection01
+ current_version_uuid: zzzzz-4zz18-logcollection01
+ portable_data_hash: 680c855fd6cf2c78778b3728b268925a+475
+ owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+ created_at: 2020-10-29T00:51:44.075594000Z
+ modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr
+ modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
+ modified_at: 2020-10-29T00:51:44.072109000Z
+ manifest_text: ". 8c12f5f5297b7337598170c6f531fcee+7882 0:0:arv-mount.txt 0:1910:container.json 1910:1264:crunch-run.txt 3174:1005:crunchstat.txt 4179:659:hoststat.txt 4838:2811:node-info.txt 7649:233:node.json 0:0:stderr.txt\n./log\\040for\\040container\\040ce8i5-dz642-h4kd64itncdcz8l 8c12f5f5297b7337598170c6f531fcee+7882 0:0:arv-mount.txt 0:1910:container.json 1910:1264:crunch-run.txt 3174:1005:crunchstat.txt 4179:659:hoststat.txt 4838:2811:node-info.txt 7649:233:node.json 0:0:stderr.txt\n"
+ name: a real log collection for a completed container
+
# Test Helper trims the rest of the file
# Do not add your fixtures below this line as the rest of this file will be trimmed by test_helper
diff --git a/services/api/test/fixtures/container_requests.yml b/services/api/test/fixtures/container_requests.yml
index ea86dca17..b3fd6b9dd 100644
--- a/services/api/test/fixtures/container_requests.yml
+++ b/services/api/test/fixtures/container_requests.yml
@@ -94,7 +94,7 @@ completed:
output_path: test
command: ["echo", "hello"]
container_uuid: zzzzz-dz642-compltcontainer
- log_uuid: zzzzz-4zz18-y9vne9npefyxh8g
+ log_uuid: zzzzz-4zz18-logcollection01
output_uuid: zzzzz-4zz18-znfnqtbbv4spc3w
runtime_constraints:
vcpus: 1
@@ -309,7 +309,7 @@ completed_with_input_mounts:
vcpus: 1
ram: 123
container_uuid: zzzzz-dz642-compltcontainer
- log_uuid: zzzzz-4zz18-y9vne9npefyxh8g
+ log_uuid: zzzzz-4zz18-logcollection01
output_uuid: zzzzz-4zz18-znfnqtbbv4spc3w
mounts:
/var/lib/cwl/cwl.input.json:
@@ -758,7 +758,7 @@ cr_in_trashed_project:
output_path: test
command: ["echo", "hello"]
container_uuid: zzzzz-dz642-compltcontainer
- log_uuid: zzzzz-4zz18-y9vne9npefyxh8g
+ log_uuid: zzzzz-4zz18-logcollection01
output_uuid: zzzzz-4zz18-znfnqtbbv4spc3w
runtime_constraints:
vcpus: 1
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list