1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: Apache-2.0
14 func (fs *customFileSystem) defaultUUID(uuid string) (string, error) {
19 err := fs.RequestAndDecode(&resp, "GET", "arvados/v1/users/current", nil, nil)
26 // loadOneChild loads only the named child, if it exists.
27 func (fs *customFileSystem) projectsLoadOne(parent inode, uuid, name string) (inode, error) {
28 uuid, err := fs.defaultUUID(uuid)
33 var contents CollectionList
34 for _, subst := range []string{"/", fs.forwardSlashNameSubstitution} {
35 contents = CollectionList{}
36 err = fs.RequestAndDecode(&contents, "GET", "arvados/v1/groups/"+uuid+"/contents", nil, ResourceListParams{
39 {"name", "=", strings.Replace(name, subst, "/", -1)},
40 {"uuid", "is_a", []string{"arvados#collection", "arvados#group"}},
41 {"groups.group_class", "=", "project"},
43 Select: []string{"uuid", "name", "modified_at", "properties"},
48 if len(contents.Items) > 0 || fs.forwardSlashNameSubstitution == "/" || fs.forwardSlashNameSubstitution == "" || !strings.Contains(name, fs.forwardSlashNameSubstitution) {
51 // If the requested name contains the configured "/"
52 // replacement string and didn't match a
53 // project/collection exactly, we'll try again with
54 // "/" in its place, so a lookup of a munged name
55 // works regardless of whether the directory listing
56 // has been populated with escaped names.
58 // Note this doesn't handle items whose names contain
59 // both "/" and the substitution string.
61 if len(contents.Items) == 0 {
64 coll := contents.Items[0]
66 if strings.Contains(coll.UUID, "-j7d0g-") {
67 // Group item was loaded into a Collection var -- but
68 // we only need the Name and UUID anyway, so it's OK.
70 inode: fs.projectSingleton(coll.UUID, &Group{
73 ModifiedAt: coll.ModifiedAt,
74 Properties: coll.Properties,
79 } else if strings.Contains(coll.UUID, "-4zz18-") {
80 return fs.newDeferredCollectionDir(parent, name, coll.UUID, coll.ModifiedAt, coll.Properties), nil
82 log.Printf("group contents: unrecognized UUID in response: %q", coll.UUID)
83 return nil, ErrInvalidArgument
87 func (fs *customFileSystem) projectsLoadAll(parent inode, uuid string) ([]inode, error) {
88 uuid, err := fs.defaultUUID(uuid)
96 // When #17424 is resolved, remove the outer loop here and use
97 // []string{"arvados#collection", "arvados#group"} directly as the uuid
99 for _, class := range []string{"arvados#collection", "arvados#group"} {
100 // Note: the "filters" slice's backing array might be reused
101 // by append(filters,...) below. This isn't goroutine safe,
102 // but all accesses are in the same goroutine, so it's OK.
104 {"uuid", "is_a", class},
106 if class == "arvados#group" {
107 filters = append(filters, Filter{"group_class", "=", "project"})
110 params := ResourceListParams{
114 Select: []string{"uuid", "name", "modified_at", "properties"},
119 // The groups content endpoint returns
120 // Collection and Group (project)
121 // objects. This function only accesses the
122 // UUID, Name, and ModifiedAt fields. Both
123 // collections and groups have those fields,
124 // so it is easier to just treat the
125 // ObjectList that comes back as a
127 var resp CollectionList
128 err = fs.RequestAndDecode(&resp, "GET", "arvados/v1/groups/"+uuid+"/contents", nil, params)
132 if len(resp.Items) == 0 {
135 for _, i := range resp.Items {
136 if fs.forwardSlashNameSubstitution != "" {
137 i.Name = strings.Replace(i.Name, "/", fs.forwardSlashNameSubstitution, -1)
139 if !permittedName(i.Name) {
142 if strings.Contains(i.UUID, "-j7d0g-") {
143 inodes = append(inodes, fs.newProjectDir(parent, i.Name, i.UUID, &Group{
146 ModifiedAt: i.ModifiedAt,
147 Properties: i.Properties,
149 } else if strings.Contains(i.UUID, "-4zz18-") {
150 inodes = append(inodes, fs.newDeferredCollectionDir(parent, i.Name, i.UUID, i.ModifiedAt, i.Properties))
152 log.Printf("group contents: unrecognized UUID in response: %q", i.UUID)
153 return nil, ErrInvalidArgument
156 params.Filters = append(filters, Filter{"uuid", ">", resp.Items[len(resp.Items)-1].UUID})
162 func (fs *customFileSystem) newProjectDir(parent inode, name, uuid string, proj *Group) inode {
163 return &hardlink{inode: fs.projectSingleton(uuid, proj), parent: parent, name: name}
166 func (fs *customFileSystem) newDeferredCollectionDir(parent inode, name, uuid string, modTime time.Time, props map[string]interface{}) inode {
167 if modTime.IsZero() {
170 placeholder := &treenode{
177 mode: 0755 | os.ModeDir,
178 sys: func() interface{} { return &Collection{UUID: uuid, Name: name, ModifiedAt: modTime, Properties: props} },
181 return &deferrednode{wrapped: placeholder, create: func() inode {
182 node, err := fs.collectionSingleton(uuid)
184 log.Printf("BUG: unhandled error: %s", err)
187 return &hardlink{inode: node, parent: parent, name: name}