20318: Use one tidying goroutine and filehandle pool per cache dir.
[arvados.git] / sdk / go / arvados / api.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 package arvados
6
7 import (
8         "bufio"
9         "context"
10         "encoding/json"
11         "io"
12         "net"
13         "net/http"
14
15         "github.com/sirupsen/logrus"
16 )
17
18 type APIEndpoint struct {
19         Method string
20         Path   string
21         // "new attributes" key for create/update requests
22         AttrsKey string
23 }
24
25 var (
26         EndpointConfigGet                     = APIEndpoint{"GET", "arvados/v1/config", ""}
27         EndpointVocabularyGet                 = APIEndpoint{"GET", "arvados/v1/vocabulary", ""}
28         EndpointDiscoveryDocument             = APIEndpoint{"GET", "discovery/v1/apis/arvados/v1/rest", ""}
29         EndpointLogin                         = APIEndpoint{"GET", "login", ""}
30         EndpointLogout                        = APIEndpoint{"GET", "logout", ""}
31         EndpointAuthorizedKeyCreate           = APIEndpoint{"POST", "arvados/v1/authorized_keys", "authorized_key"}
32         EndpointAuthorizedKeyUpdate           = APIEndpoint{"PATCH", "arvados/v1/authorized_keys/{uuid}", "authorized_key"}
33         EndpointAuthorizedKeyGet              = APIEndpoint{"GET", "arvados/v1/authorized_keys/{uuid}", ""}
34         EndpointAuthorizedKeyList             = APIEndpoint{"GET", "arvados/v1/authorized_keys", ""}
35         EndpointAuthorizedKeyDelete           = APIEndpoint{"DELETE", "arvados/v1/authorized_keys/{uuid}", ""}
36         EndpointCollectionCreate              = APIEndpoint{"POST", "arvados/v1/collections", "collection"}
37         EndpointCollectionUpdate              = APIEndpoint{"PATCH", "arvados/v1/collections/{uuid}", "collection"}
38         EndpointCollectionGet                 = APIEndpoint{"GET", "arvados/v1/collections/{uuid}", ""}
39         EndpointCollectionList                = APIEndpoint{"GET", "arvados/v1/collections", ""}
40         EndpointCollectionProvenance          = APIEndpoint{"GET", "arvados/v1/collections/{uuid}/provenance", ""}
41         EndpointCollectionUsedBy              = APIEndpoint{"GET", "arvados/v1/collections/{uuid}/used_by", ""}
42         EndpointCollectionDelete              = APIEndpoint{"DELETE", "arvados/v1/collections/{uuid}", ""}
43         EndpointCollectionTrash               = APIEndpoint{"POST", "arvados/v1/collections/{uuid}/trash", ""}
44         EndpointCollectionUntrash             = APIEndpoint{"POST", "arvados/v1/collections/{uuid}/untrash", ""}
45         EndpointSpecimenCreate                = APIEndpoint{"POST", "arvados/v1/specimens", "specimen"}
46         EndpointSpecimenUpdate                = APIEndpoint{"PATCH", "arvados/v1/specimens/{uuid}", "specimen"}
47         EndpointSpecimenGet                   = APIEndpoint{"GET", "arvados/v1/specimens/{uuid}", ""}
48         EndpointSpecimenList                  = APIEndpoint{"GET", "arvados/v1/specimens", ""}
49         EndpointSpecimenDelete                = APIEndpoint{"DELETE", "arvados/v1/specimens/{uuid}", ""}
50         EndpointContainerCreate               = APIEndpoint{"POST", "arvados/v1/containers", "container"}
51         EndpointContainerUpdate               = APIEndpoint{"PATCH", "arvados/v1/containers/{uuid}", "container"}
52         EndpointContainerPriorityUpdate       = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/update_priority", "container"}
53         EndpointContainerGet                  = APIEndpoint{"GET", "arvados/v1/containers/{uuid}", ""}
54         EndpointContainerList                 = APIEndpoint{"GET", "arvados/v1/containers", ""}
55         EndpointContainerDelete               = APIEndpoint{"DELETE", "arvados/v1/containers/{uuid}", ""}
56         EndpointContainerLock                 = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/lock", ""}
57         EndpointContainerUnlock               = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/unlock", ""}
58         EndpointContainerSSH                  = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/ssh", ""}
59         EndpointContainerSSHCompat            = APIEndpoint{"POST", "arvados/v1/connect/{uuid}/ssh", ""} // for compatibility with arvados <2.7
60         EndpointContainerGatewayTunnel        = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/gateway_tunnel", ""}
61         EndpointContainerGatewayTunnelCompat  = APIEndpoint{"POST", "arvados/v1/connect/{uuid}/gateway_tunnel", ""} // for compatibility with arvados <2.7
62         EndpointContainerRequestCreate        = APIEndpoint{"POST", "arvados/v1/container_requests", "container_request"}
63         EndpointContainerRequestUpdate        = APIEndpoint{"PATCH", "arvados/v1/container_requests/{uuid}", "container_request"}
64         EndpointContainerRequestGet           = APIEndpoint{"GET", "arvados/v1/container_requests/{uuid}", ""}
65         EndpointContainerRequestList          = APIEndpoint{"GET", "arvados/v1/container_requests", ""}
66         EndpointContainerRequestDelete        = APIEndpoint{"DELETE", "arvados/v1/container_requests/{uuid}", ""}
67         EndpointContainerRequestLog           = APIEndpoint{"GET", "arvados/v1/container_requests/{uuid}/log{path:|/.*}", ""}
68         EndpointGroupCreate                   = APIEndpoint{"POST", "arvados/v1/groups", "group"}
69         EndpointGroupUpdate                   = APIEndpoint{"PATCH", "arvados/v1/groups/{uuid}", "group"}
70         EndpointGroupGet                      = APIEndpoint{"GET", "arvados/v1/groups/{uuid}", ""}
71         EndpointGroupList                     = APIEndpoint{"GET", "arvados/v1/groups", ""}
72         EndpointGroupContents                 = APIEndpoint{"GET", "arvados/v1/groups/contents", ""}
73         EndpointGroupContentsUUIDInPath       = APIEndpoint{"GET", "arvados/v1/groups/{uuid}/contents", ""} // Alternative HTTP route; client-side code should always use EndpointGroupContents instead
74         EndpointGroupShared                   = APIEndpoint{"GET", "arvados/v1/groups/shared", ""}
75         EndpointGroupDelete                   = APIEndpoint{"DELETE", "arvados/v1/groups/{uuid}", ""}
76         EndpointGroupTrash                    = APIEndpoint{"POST", "arvados/v1/groups/{uuid}/trash", ""}
77         EndpointGroupUntrash                  = APIEndpoint{"POST", "arvados/v1/groups/{uuid}/untrash", ""}
78         EndpointLinkCreate                    = APIEndpoint{"POST", "arvados/v1/links", "link"}
79         EndpointLinkUpdate                    = APIEndpoint{"PATCH", "arvados/v1/links/{uuid}", "link"}
80         EndpointLinkGet                       = APIEndpoint{"GET", "arvados/v1/links/{uuid}", ""}
81         EndpointLinkList                      = APIEndpoint{"GET", "arvados/v1/links", ""}
82         EndpointLinkDelete                    = APIEndpoint{"DELETE", "arvados/v1/links/{uuid}", ""}
83         EndpointLogCreate                     = APIEndpoint{"POST", "arvados/v1/logs", "log"}
84         EndpointLogUpdate                     = APIEndpoint{"PATCH", "arvados/v1/logs/{uuid}", "log"}
85         EndpointLogGet                        = APIEndpoint{"GET", "arvados/v1/logs/{uuid}", ""}
86         EndpointLogList                       = APIEndpoint{"GET", "arvados/v1/logs", ""}
87         EndpointLogDelete                     = APIEndpoint{"DELETE", "arvados/v1/logs/{uuid}", ""}
88         EndpointSysTrashSweep                 = APIEndpoint{"POST", "sys/trash_sweep", ""}
89         EndpointUserActivate                  = APIEndpoint{"POST", "arvados/v1/users/{uuid}/activate", ""}
90         EndpointUserCreate                    = APIEndpoint{"POST", "arvados/v1/users", "user"}
91         EndpointUserCurrent                   = APIEndpoint{"GET", "arvados/v1/users/current", ""}
92         EndpointUserDelete                    = APIEndpoint{"DELETE", "arvados/v1/users/{uuid}", ""}
93         EndpointUserGet                       = APIEndpoint{"GET", "arvados/v1/users/{uuid}", ""}
94         EndpointUserGetCurrent                = APIEndpoint{"GET", "arvados/v1/users/current", ""}
95         EndpointUserGetSystem                 = APIEndpoint{"GET", "arvados/v1/users/system", ""}
96         EndpointUserList                      = APIEndpoint{"GET", "arvados/v1/users", ""}
97         EndpointUserMerge                     = APIEndpoint{"POST", "arvados/v1/users/merge", ""}
98         EndpointUserSetup                     = APIEndpoint{"POST", "arvados/v1/users/setup", "user"}
99         EndpointUserSystem                    = APIEndpoint{"GET", "arvados/v1/users/system", ""}
100         EndpointUserUnsetup                   = APIEndpoint{"POST", "arvados/v1/users/{uuid}/unsetup", ""}
101         EndpointUserUpdate                    = APIEndpoint{"PATCH", "arvados/v1/users/{uuid}", "user"}
102         EndpointUserBatchUpdate               = APIEndpoint{"PATCH", "arvados/v1/users/batch_update", ""}
103         EndpointUserAuthenticate              = APIEndpoint{"POST", "arvados/v1/users/authenticate", ""}
104         EndpointAPIClientAuthorizationCurrent = APIEndpoint{"GET", "arvados/v1/api_client_authorizations/current", ""}
105         EndpointAPIClientAuthorizationCreate  = APIEndpoint{"POST", "arvados/v1/api_client_authorizations", "api_client_authorization"}
106         EndpointAPIClientAuthorizationUpdate  = APIEndpoint{"PUT", "arvados/v1/api_client_authorizations/{uuid}", "api_client_authorization"}
107         EndpointAPIClientAuthorizationList    = APIEndpoint{"GET", "arvados/v1/api_client_authorizations", ""}
108         EndpointAPIClientAuthorizationDelete  = APIEndpoint{"DELETE", "arvados/v1/api_client_authorizations/{uuid}", ""}
109         EndpointAPIClientAuthorizationGet     = APIEndpoint{"GET", "arvados/v1/api_client_authorizations/{uuid}", ""}
110 )
111
112 type ContainerSSHOptions struct {
113         UUID          string `json:"uuid"`
114         DetachKeys    string `json:"detach_keys"`
115         LoginUsername string `json:"login_username"`
116         NoForward     bool   `json:"no_forward"`
117 }
118
119 type ConnectionResponse struct {
120         Conn   net.Conn           `json:"-"`
121         Bufrw  *bufio.ReadWriter  `json:"-"`
122         Logger logrus.FieldLogger `json:"-"`
123         Header http.Header        `json:"-"`
124 }
125
126 type ContainerGatewayTunnelOptions struct {
127         UUID       string `json:"uuid"`
128         AuthSecret string `json:"auth_secret"`
129 }
130
131 type GetOptions struct {
132         UUID         string   `json:"uuid,omitempty"`
133         Select       []string `json:"select"`
134         IncludeTrash bool     `json:"include_trash"`
135         ForwardedFor string   `json:"forwarded_for,omitempty"`
136         Remote       string   `json:"remote,omitempty"`
137 }
138
139 type UntrashOptions struct {
140         UUID             string `json:"uuid"`
141         EnsureUniqueName bool   `json:"ensure_unique_name"`
142 }
143
144 type ListOptions struct {
145         ClusterID          string                 `json:"cluster_id"`
146         Select             []string               `json:"select"`
147         Filters            []Filter               `json:"filters"`
148         Where              map[string]interface{} `json:"where"`
149         Limit              int64                  `json:"limit"`
150         Offset             int64                  `json:"offset"`
151         Order              []string               `json:"order"`
152         Distinct           bool                   `json:"distinct"`
153         Count              string                 `json:"count"`
154         IncludeTrash       bool                   `json:"include_trash"`
155         IncludeOldVersions bool                   `json:"include_old_versions"`
156         BypassFederation   bool                   `json:"bypass_federation"`
157         ForwardedFor       string                 `json:"forwarded_for,omitempty"`
158         Include            string                 `json:"include"`
159 }
160
161 type CreateOptions struct {
162         ClusterID        string                 `json:"cluster_id"`
163         EnsureUniqueName bool                   `json:"ensure_unique_name"`
164         Select           []string               `json:"select"`
165         Attrs            map[string]interface{} `json:"attrs"`
166         // ReplaceFiles only applies when creating a collection.
167         ReplaceFiles map[string]string `json:"replace_files"`
168 }
169
170 type UpdateOptions struct {
171         UUID             string                 `json:"uuid"`
172         Attrs            map[string]interface{} `json:"attrs"`
173         Select           []string               `json:"select"`
174         BypassFederation bool                   `json:"bypass_federation"`
175         // ReplaceFiles only applies when updating a collection.
176         ReplaceFiles map[string]string `json:"replace_files"`
177 }
178
179 type GroupContentsOptions struct {
180         ClusterID          string   `json:"cluster_id"`
181         UUID               string   `json:"uuid,omitempty"`
182         Select             []string `json:"select"`
183         Filters            []Filter `json:"filters"`
184         Limit              int64    `json:"limit"`
185         Offset             int64    `json:"offset"`
186         Order              []string `json:"order"`
187         Distinct           bool     `json:"distinct"`
188         Count              string   `json:"count"`
189         Include            string   `json:"include"`
190         Recursive          bool     `json:"recursive"`
191         IncludeTrash       bool     `json:"include_trash"`
192         IncludeOldVersions bool     `json:"include_old_versions"`
193         ExcludeHomeProject bool     `json:"exclude_home_project"`
194 }
195
196 type UserActivateOptions struct {
197         UUID string `json:"uuid"`
198 }
199
200 type UserSetupOptions struct {
201         UUID                  string                 `json:"uuid,omitempty"`
202         Email                 string                 `json:"email,omitempty"`
203         OpenIDPrefix          string                 `json:"openid_prefix,omitempty"`
204         RepoName              string                 `json:"repo_name,omitempty"`
205         VMUUID                string                 `json:"vm_uuid,omitempty"`
206         SendNotificationEmail bool                   `json:"send_notification_email,omitempty"`
207         Attrs                 map[string]interface{} `json:"attrs"`
208 }
209
210 type UserMergeOptions struct {
211         NewUserUUID       string `json:"new_user_uuid,omitempty"`
212         OldUserUUID       string `json:"old_user_uuid,omitempty"`
213         NewOwnerUUID      string `json:"new_owner_uuid,omitempty"`
214         NewUserToken      string `json:"new_user_token,omitempty"`
215         RedirectToNewUser bool   `json:"redirect_to_new_user"`
216 }
217
218 type UserBatchUpdateOptions struct {
219         Updates map[string]map[string]interface{} `json:"updates"`
220 }
221
222 type UserBatchUpdateResponse struct{}
223
224 type DeleteOptions struct {
225         UUID string `json:"uuid"`
226 }
227
228 type LoginOptions struct {
229         ReturnTo string `json:"return_to"`        // On success, redirect to this target with api_token=xxx query param
230         Remote   string `json:"remote,omitempty"` // Salt token for remote Cluster ID
231         Code     string `json:"code,omitempty"`   // OAuth2 callback code
232         State    string `json:"state,omitempty"`  // OAuth2 callback state
233 }
234
235 type UserAuthenticateOptions struct {
236         Username string `json:"username,omitempty"` // PAM username
237         Password string `json:"password,omitempty"` // PAM password
238 }
239
240 type LogoutOptions struct {
241         ReturnTo string `json:"return_to"` // Redirect to this URL after logging out
242 }
243
244 type BlockReadOptions struct {
245         Locator string
246         WriteTo io.Writer
247 }
248
249 type BlockWriteOptions struct {
250         Hash           string
251         Data           []byte
252         Reader         io.Reader // Must be set if Data is nil.
253         DataSize       int       // Must be set if Data is nil.
254         RequestID      string
255         StorageClasses []string
256         Replicas       int
257         Attempts       int
258 }
259
260 type BlockWriteResponse struct {
261         Locator  string
262         Replicas int
263 }
264
265 type WebDAVOptions struct {
266         Method string
267         Path   string
268         Header http.Header
269 }
270
271 type ContainerLogOptions struct {
272         UUID      string `json:"uuid"`
273         NoForward bool   `json:"no_forward"`
274         WebDAVOptions
275 }
276
277 type API interface {
278         ConfigGet(ctx context.Context) (json.RawMessage, error)
279         VocabularyGet(ctx context.Context) (Vocabulary, error)
280         Login(ctx context.Context, options LoginOptions) (LoginResponse, error)
281         Logout(ctx context.Context, options LogoutOptions) (LogoutResponse, error)
282         AuthorizedKeyCreate(ctx context.Context, options CreateOptions) (AuthorizedKey, error)
283         AuthorizedKeyUpdate(ctx context.Context, options UpdateOptions) (AuthorizedKey, error)
284         AuthorizedKeyGet(ctx context.Context, options GetOptions) (AuthorizedKey, error)
285         AuthorizedKeyList(ctx context.Context, options ListOptions) (AuthorizedKeyList, error)
286         AuthorizedKeyDelete(ctx context.Context, options DeleteOptions) (AuthorizedKey, error)
287         CollectionCreate(ctx context.Context, options CreateOptions) (Collection, error)
288         CollectionUpdate(ctx context.Context, options UpdateOptions) (Collection, error)
289         CollectionGet(ctx context.Context, options GetOptions) (Collection, error)
290         CollectionList(ctx context.Context, options ListOptions) (CollectionList, error)
291         CollectionProvenance(ctx context.Context, options GetOptions) (map[string]interface{}, error)
292         CollectionUsedBy(ctx context.Context, options GetOptions) (map[string]interface{}, error)
293         CollectionDelete(ctx context.Context, options DeleteOptions) (Collection, error)
294         CollectionTrash(ctx context.Context, options DeleteOptions) (Collection, error)
295         CollectionUntrash(ctx context.Context, options UntrashOptions) (Collection, error)
296         ContainerCreate(ctx context.Context, options CreateOptions) (Container, error)
297         ContainerUpdate(ctx context.Context, options UpdateOptions) (Container, error)
298         ContainerPriorityUpdate(ctx context.Context, options UpdateOptions) (Container, error)
299         ContainerGet(ctx context.Context, options GetOptions) (Container, error)
300         ContainerList(ctx context.Context, options ListOptions) (ContainerList, error)
301         ContainerDelete(ctx context.Context, options DeleteOptions) (Container, error)
302         ContainerLock(ctx context.Context, options GetOptions) (Container, error)
303         ContainerUnlock(ctx context.Context, options GetOptions) (Container, error)
304         ContainerSSH(ctx context.Context, options ContainerSSHOptions) (ConnectionResponse, error)
305         ContainerGatewayTunnel(ctx context.Context, options ContainerGatewayTunnelOptions) (ConnectionResponse, error)
306         ContainerRequestCreate(ctx context.Context, options CreateOptions) (ContainerRequest, error)
307         ContainerRequestUpdate(ctx context.Context, options UpdateOptions) (ContainerRequest, error)
308         ContainerRequestGet(ctx context.Context, options GetOptions) (ContainerRequest, error)
309         ContainerRequestList(ctx context.Context, options ListOptions) (ContainerRequestList, error)
310         ContainerRequestDelete(ctx context.Context, options DeleteOptions) (ContainerRequest, error)
311         ContainerRequestLog(ctx context.Context, options ContainerLogOptions) (http.Handler, error)
312         GroupCreate(ctx context.Context, options CreateOptions) (Group, error)
313         GroupUpdate(ctx context.Context, options UpdateOptions) (Group, error)
314         GroupGet(ctx context.Context, options GetOptions) (Group, error)
315         GroupList(ctx context.Context, options ListOptions) (GroupList, error)
316         GroupContents(ctx context.Context, options GroupContentsOptions) (ObjectList, error)
317         GroupShared(ctx context.Context, options ListOptions) (GroupList, error)
318         GroupDelete(ctx context.Context, options DeleteOptions) (Group, error)
319         GroupTrash(ctx context.Context, options DeleteOptions) (Group, error)
320         GroupUntrash(ctx context.Context, options UntrashOptions) (Group, error)
321         LinkCreate(ctx context.Context, options CreateOptions) (Link, error)
322         LinkUpdate(ctx context.Context, options UpdateOptions) (Link, error)
323         LinkGet(ctx context.Context, options GetOptions) (Link, error)
324         LinkList(ctx context.Context, options ListOptions) (LinkList, error)
325         LinkDelete(ctx context.Context, options DeleteOptions) (Link, error)
326         LogCreate(ctx context.Context, options CreateOptions) (Log, error)
327         LogUpdate(ctx context.Context, options UpdateOptions) (Log, error)
328         LogGet(ctx context.Context, options GetOptions) (Log, error)
329         LogList(ctx context.Context, options ListOptions) (LogList, error)
330         LogDelete(ctx context.Context, options DeleteOptions) (Log, error)
331         SpecimenCreate(ctx context.Context, options CreateOptions) (Specimen, error)
332         SpecimenUpdate(ctx context.Context, options UpdateOptions) (Specimen, error)
333         SpecimenGet(ctx context.Context, options GetOptions) (Specimen, error)
334         SpecimenList(ctx context.Context, options ListOptions) (SpecimenList, error)
335         SpecimenDelete(ctx context.Context, options DeleteOptions) (Specimen, error)
336         SysTrashSweep(ctx context.Context, options struct{}) (struct{}, error)
337         UserCreate(ctx context.Context, options CreateOptions) (User, error)
338         UserUpdate(ctx context.Context, options UpdateOptions) (User, error)
339         UserMerge(ctx context.Context, options UserMergeOptions) (User, error)
340         UserActivate(ctx context.Context, options UserActivateOptions) (User, error)
341         UserSetup(ctx context.Context, options UserSetupOptions) (map[string]interface{}, error)
342         UserUnsetup(ctx context.Context, options GetOptions) (User, error)
343         UserGet(ctx context.Context, options GetOptions) (User, error)
344         UserGetCurrent(ctx context.Context, options GetOptions) (User, error)
345         UserGetSystem(ctx context.Context, options GetOptions) (User, error)
346         UserList(ctx context.Context, options ListOptions) (UserList, error)
347         UserDelete(ctx context.Context, options DeleteOptions) (User, error)
348         UserBatchUpdate(context.Context, UserBatchUpdateOptions) (UserList, error)
349         UserAuthenticate(ctx context.Context, options UserAuthenticateOptions) (APIClientAuthorization, error)
350         APIClientAuthorizationCurrent(ctx context.Context, options GetOptions) (APIClientAuthorization, error)
351         APIClientAuthorizationCreate(ctx context.Context, options CreateOptions) (APIClientAuthorization, error)
352         APIClientAuthorizationList(ctx context.Context, options ListOptions) (APIClientAuthorizationList, error)
353         APIClientAuthorizationDelete(ctx context.Context, options DeleteOptions) (APIClientAuthorization, error)
354         APIClientAuthorizationUpdate(ctx context.Context, options UpdateOptions) (APIClientAuthorization, error)
355         APIClientAuthorizationGet(ctx context.Context, options GetOptions) (APIClientAuthorization, error)
356         DiscoveryDocument(ctx context.Context) (DiscoveryDocument, error)
357 }