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{
40 {"name", "=", strings.Replace(name, subst, "/", -1)},
41 {"uuid", "is_a", []string{"arvados#collection", "arvados#group"}},
42 {"groups.group_class", "in", []string{"project", "filter"}},
44 Select: []string{"uuid", "name", "modified_at", "properties"},
49 if len(contents.Items) > 0 || fs.forwardSlashNameSubstitution == "/" || fs.forwardSlashNameSubstitution == "" || !strings.Contains(name, fs.forwardSlashNameSubstitution) {
52 // If the requested name contains the configured "/"
53 // replacement string and didn't match a
54 // project/collection exactly, we'll try again with
55 // "/" in its place, so a lookup of a munged name
56 // works regardless of whether the directory listing
57 // has been populated with escaped names.
59 // Note this doesn't handle items whose names contain
60 // both "/" and the substitution string.
62 if len(contents.Items) == 0 {
65 coll := contents.Items[0]
67 if strings.Contains(coll.UUID, "-j7d0g-") {
68 // Group item was loaded into a Collection var -- but
69 // we only need the Name and UUID anyway, so it's OK.
71 inode: fs.projectSingleton(coll.UUID, &Group{
74 ModifiedAt: coll.ModifiedAt,
75 Properties: coll.Properties,
80 } else if strings.Contains(coll.UUID, "-4zz18-") {
81 return fs.newDeferredCollectionDir(parent, name, coll.UUID, coll.ModifiedAt, coll.Properties), nil
83 log.Printf("group contents: unrecognized UUID in response: %q", coll.UUID)
84 return nil, ErrInvalidArgument
88 func (fs *customFileSystem) projectsLoadAll(parent inode, uuid string) ([]inode, error) {
89 uuid, err := fs.defaultUUID(uuid)
97 // When #17424 is resolved, remove the outer loop here and use
98 // []string{"arvados#collection", "arvados#group"} directly as the uuid
100 for _, class := range []string{"arvados#collection", "arvados#group"} {
101 // Note: the "filters" slice's backing array might be reused
102 // by append(filters,...) below. This isn't goroutine safe,
103 // but all accesses are in the same goroutine, so it's OK.
105 {"uuid", "is_a", class},
107 if class == "arvados#group" {
108 filters = append(filters, Filter{"groups.group_class", "in", []string{"project", "filter"}})
111 params := ResourceListParams{
115 Select: []string{"uuid", "name", "modified_at", "properties"},
120 // The groups content endpoint returns
121 // Collection and Group (project)
122 // objects. This function only accesses the
123 // UUID, Name, and ModifiedAt fields. Both
124 // collections and groups have those fields,
125 // so it is easier to just treat the
126 // ObjectList that comes back as a
128 var resp CollectionList
129 err = fs.RequestAndDecode(&resp, "GET", "arvados/v1/groups/"+uuid+"/contents", nil, params)
133 if len(resp.Items) == 0 {
136 for _, i := range resp.Items {
137 if fs.forwardSlashNameSubstitution != "" {
138 i.Name = strings.Replace(i.Name, "/", fs.forwardSlashNameSubstitution, -1)
140 if !permittedName(i.Name) {
143 if strings.Contains(i.UUID, "-j7d0g-") {
144 inodes = append(inodes, fs.newProjectDir(parent, i.Name, i.UUID, &Group{
147 ModifiedAt: i.ModifiedAt,
148 Properties: i.Properties,
150 } else if strings.Contains(i.UUID, "-4zz18-") {
151 inodes = append(inodes, fs.newDeferredCollectionDir(parent, i.Name, i.UUID, i.ModifiedAt, i.Properties))
153 log.Printf("group contents: unrecognized UUID in response: %q", i.UUID)
154 return nil, ErrInvalidArgument
157 params.Filters = append(filters, Filter{"uuid", ">", resp.Items[len(resp.Items)-1].UUID})
163 func (fs *customFileSystem) newProjectDir(parent inode, name, uuid string, proj *Group) inode {
164 return &hardlink{inode: fs.projectSingleton(uuid, proj), parent: parent, name: name}
167 func (fs *customFileSystem) newDeferredCollectionDir(parent inode, name, uuid string, modTime time.Time, props map[string]interface{}) inode {
168 if modTime.IsZero() {
171 placeholder := &treenode{
178 mode: 0755 | os.ModeDir,
179 sys: func() interface{} { return &Collection{UUID: uuid, Name: name, ModifiedAt: modTime, Properties: props} },
182 return &deferrednode{wrapped: placeholder, create: func() inode {
183 node, err := fs.collectionSingleton(uuid)
185 log.Printf("BUG: unhandled error: %s", err)
188 return &hardlink{inode: node, parent: parent, name: name}