17589: Ensure that 'group contents' requests are routed correctly
[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         "net"
12
13         "github.com/sirupsen/logrus"
14 )
15
16 type APIEndpoint struct {
17         Method string
18         Path   string
19         // "new attributes" key for create/update requests
20         AttrsKey string
21 }
22
23 var (
24         EndpointConfigGet                     = APIEndpoint{"GET", "arvados/v1/config", ""}
25         EndpointLogin                         = APIEndpoint{"GET", "login", ""}
26         EndpointLogout                        = APIEndpoint{"GET", "logout", ""}
27         EndpointCollectionCreate              = APIEndpoint{"POST", "arvados/v1/collections", "collection"}
28         EndpointCollectionUpdate              = APIEndpoint{"PATCH", "arvados/v1/collections/{uuid}", "collection"}
29         EndpointCollectionGet                 = APIEndpoint{"GET", "arvados/v1/collections/{uuid}", ""}
30         EndpointCollectionList                = APIEndpoint{"GET", "arvados/v1/collections", ""}
31         EndpointCollectionProvenance          = APIEndpoint{"GET", "arvados/v1/collections/{uuid}/provenance", ""}
32         EndpointCollectionUsedBy              = APIEndpoint{"GET", "arvados/v1/collections/{uuid}/used_by", ""}
33         EndpointCollectionDelete              = APIEndpoint{"DELETE", "arvados/v1/collections/{uuid}", ""}
34         EndpointCollectionTrash               = APIEndpoint{"POST", "arvados/v1/collections/{uuid}/trash", ""}
35         EndpointCollectionUntrash             = APIEndpoint{"POST", "arvados/v1/collections/{uuid}/untrash", ""}
36         EndpointSpecimenCreate                = APIEndpoint{"POST", "arvados/v1/specimens", "specimen"}
37         EndpointSpecimenUpdate                = APIEndpoint{"PATCH", "arvados/v1/specimens/{uuid}", "specimen"}
38         EndpointSpecimenGet                   = APIEndpoint{"GET", "arvados/v1/specimens/{uuid}", ""}
39         EndpointSpecimenList                  = APIEndpoint{"GET", "arvados/v1/specimens", ""}
40         EndpointSpecimenDelete                = APIEndpoint{"DELETE", "arvados/v1/specimens/{uuid}", ""}
41         EndpointContainerCreate               = APIEndpoint{"POST", "arvados/v1/containers", "container"}
42         EndpointContainerUpdate               = APIEndpoint{"PATCH", "arvados/v1/containers/{uuid}", "container"}
43         EndpointContainerGet                  = APIEndpoint{"GET", "arvados/v1/containers/{uuid}", ""}
44         EndpointContainerList                 = APIEndpoint{"GET", "arvados/v1/containers", ""}
45         EndpointContainerDelete               = APIEndpoint{"DELETE", "arvados/v1/containers/{uuid}", ""}
46         EndpointContainerLock                 = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/lock", ""}
47         EndpointContainerUnlock               = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/unlock", ""}
48         EndpointContainerSSH                  = APIEndpoint{"GET", "arvados/v1/connect/{uuid}/ssh", ""} // move to /containers after #17014 fixes routing
49         EndpointContainerRequestCreate        = APIEndpoint{"POST", "arvados/v1/container_requests", "container_request"}
50         EndpointContainerRequestUpdate        = APIEndpoint{"PATCH", "arvados/v1/container_requests/{uuid}", "container_request"}
51         EndpointContainerRequestGet           = APIEndpoint{"GET", "arvados/v1/container_requests/{uuid}", ""}
52         EndpointContainerRequestList          = APIEndpoint{"GET", "arvados/v1/container_requests", ""}
53         EndpointContainerRequestDelete        = APIEndpoint{"DELETE", "arvados/v1/container_requests/{uuid}", ""}
54         EndpointGroupCreate                   = APIEndpoint{"POST", "arvados/v1/groups", "group"}
55         EndpointGroupUpdate                   = APIEndpoint{"PATCH", "arvados/v1/groups/{uuid}", "group"}
56         EndpointGroupGet                      = APIEndpoint{"GET", "arvados/v1/groups/{uuid}", ""}
57         EndpointGroupList                     = APIEndpoint{"GET", "arvados/v1/groups", ""}
58         EndpointGroupContents                 = APIEndpoint{"GET", "arvados/v1/groups/contents", ""}
59         EndpointGroupContentsUUIDInPath       = APIEndpoint{"GET", "arvados/v1/groups/{uuid}/contents", ""} // Alternative HTTP route; client-side code should always use EndpointGroupContents instead
60         EndpointGroupShared                   = APIEndpoint{"GET", "arvados/v1/groups/shared", ""}
61         EndpointGroupDelete                   = APIEndpoint{"DELETE", "arvados/v1/groups/{uuid}", ""}
62         EndpointGroupTrash                    = APIEndpoint{"POST", "arvados/v1/groups/{uuid}/trash", ""}
63         EndpointGroupUntrash                  = APIEndpoint{"POST", "arvados/v1/groups/{uuid}/untrash", ""}
64         EndpointUserActivate                  = APIEndpoint{"POST", "arvados/v1/users/{uuid}/activate", ""}
65         EndpointUserCreate                    = APIEndpoint{"POST", "arvados/v1/users", "user"}
66         EndpointUserCurrent                   = APIEndpoint{"GET", "arvados/v1/users/current", ""}
67         EndpointUserDelete                    = APIEndpoint{"DELETE", "arvados/v1/users/{uuid}", ""}
68         EndpointUserGet                       = APIEndpoint{"GET", "arvados/v1/users/{uuid}", ""}
69         EndpointUserGetCurrent                = APIEndpoint{"GET", "arvados/v1/users/current", ""}
70         EndpointUserGetSystem                 = APIEndpoint{"GET", "arvados/v1/users/system", ""}
71         EndpointUserList                      = APIEndpoint{"GET", "arvados/v1/users", ""}
72         EndpointUserMerge                     = APIEndpoint{"POST", "arvados/v1/users/merge", ""}
73         EndpointUserSetup                     = APIEndpoint{"POST", "arvados/v1/users/setup", "user"}
74         EndpointUserSystem                    = APIEndpoint{"GET", "arvados/v1/users/system", ""}
75         EndpointUserUnsetup                   = APIEndpoint{"POST", "arvados/v1/users/{uuid}/unsetup", ""}
76         EndpointUserUpdate                    = APIEndpoint{"PATCH", "arvados/v1/users/{uuid}", "user"}
77         EndpointUserUpdateUUID                = APIEndpoint{"POST", "arvados/v1/users/{uuid}/update_uuid", ""}
78         EndpointUserBatchUpdate               = APIEndpoint{"PATCH", "arvados/v1/users/batch_update", ""}
79         EndpointUserAuthenticate              = APIEndpoint{"POST", "arvados/v1/users/authenticate", ""}
80         EndpointAPIClientAuthorizationCurrent = APIEndpoint{"GET", "arvados/v1/api_client_authorizations/current", ""}
81 )
82
83 type ContainerSSHOptions struct {
84         UUID          string `json:"uuid"`
85         DetachKeys    string `json:"detach_keys"`
86         LoginUsername string `json:"login_username"`
87 }
88
89 type ContainerSSHConnection struct {
90         Conn   net.Conn           `json:"-"`
91         Bufrw  *bufio.ReadWriter  `json:"-"`
92         Logger logrus.FieldLogger `json:"-"`
93 }
94
95 type GetOptions struct {
96         UUID         string   `json:"uuid,omitempty"`
97         Select       []string `json:"select"`
98         IncludeTrash bool     `json:"include_trash"`
99         ForwardedFor string   `json:"forwarded_for,omitempty"`
100         Remote       string   `json:"remote,omitempty"`
101 }
102
103 type UntrashOptions struct {
104         UUID             string `json:"uuid"`
105         EnsureUniqueName bool   `json:"ensure_unique_name"`
106 }
107
108 type ListOptions struct {
109         ClusterID          string                 `json:"cluster_id"`
110         Select             []string               `json:"select"`
111         Filters            []Filter               `json:"filters"`
112         Where              map[string]interface{} `json:"where"`
113         Limit              int64                  `json:"limit"`
114         Offset             int64                  `json:"offset"`
115         Order              []string               `json:"order"`
116         Distinct           bool                   `json:"distinct"`
117         Count              string                 `json:"count"`
118         IncludeTrash       bool                   `json:"include_trash"`
119         IncludeOldVersions bool                   `json:"include_old_versions"`
120         BypassFederation   bool                   `json:"bypass_federation"`
121         ForwardedFor       string                 `json:"forwarded_for,omitempty"`
122         Include            string                 `json:"include"`
123 }
124
125 type CreateOptions struct {
126         ClusterID        string                 `json:"cluster_id"`
127         EnsureUniqueName bool                   `json:"ensure_unique_name"`
128         Select           []string               `json:"select"`
129         Attrs            map[string]interface{} `json:"attrs"`
130 }
131
132 type UpdateOptions struct {
133         UUID             string                 `json:"uuid"`
134         Attrs            map[string]interface{} `json:"attrs"`
135         BypassFederation bool                   `json:"bypass_federation"`
136 }
137
138 type GroupContentsOptions struct {
139         ClusterID          string   `json:"cluster_id"`
140         UUID               string   `json:"uuid,omitempty"`
141         Select             []string `json:"select"`
142         Filters            []Filter `json:"filters"`
143         Limit              int64    `json:"limit"`
144         Offset             int64    `json:"offset"`
145         Order              []string `json:"order"`
146         Distinct           bool     `json:"distinct"`
147         Count              string   `json:"count"`
148         Include            string   `json:"include"`
149         Recursive          bool     `json:"recursive"`
150         IncludeTrash       bool     `json:"include_trash"`
151         IncludeOldVersions bool     `json:"include_old_versions"`
152         ExcludeHomeProject bool     `json:"exclude_home_project"`
153 }
154
155 type UpdateUUIDOptions struct {
156         UUID    string `json:"uuid"`
157         NewUUID string `json:"new_uuid"`
158 }
159
160 type UserActivateOptions struct {
161         UUID string `json:"uuid"`
162 }
163
164 type UserSetupOptions struct {
165         UUID                  string                 `json:"uuid,omitempty"`
166         Email                 string                 `json:"email,omitempty"`
167         OpenIDPrefix          string                 `json:"openid_prefix,omitempty"`
168         RepoName              string                 `json:"repo_name,omitempty"`
169         VMUUID                string                 `json:"vm_uuid,omitempty"`
170         SendNotificationEmail bool                   `json:"send_notification_email,omitempty"`
171         Attrs                 map[string]interface{} `json:"attrs"`
172 }
173
174 type UserMergeOptions struct {
175         NewUserUUID       string `json:"new_user_uuid,omitempty"`
176         OldUserUUID       string `json:"old_user_uuid,omitempty"`
177         NewOwnerUUID      string `json:"new_owner_uuid,omitempty"`
178         NewUserToken      string `json:"new_user_token,omitempty"`
179         RedirectToNewUser bool   `json:"redirect_to_new_user"`
180 }
181
182 type UserBatchUpdateOptions struct {
183         Updates map[string]map[string]interface{} `json:"updates"`
184 }
185
186 type UserBatchUpdateResponse struct{}
187
188 type DeleteOptions struct {
189         UUID string `json:"uuid"`
190 }
191
192 type LoginOptions struct {
193         ReturnTo string `json:"return_to"`        // On success, redirect to this target with api_token=xxx query param
194         Remote   string `json:"remote,omitempty"` // Salt token for remote Cluster ID
195         Code     string `json:"code,omitempty"`   // OAuth2 callback code
196         State    string `json:"state,omitempty"`  // OAuth2 callback state
197 }
198
199 type UserAuthenticateOptions struct {
200         Username string `json:"username,omitempty"` // PAM username
201         Password string `json:"password,omitempty"` // PAM password
202 }
203
204 type LogoutOptions struct {
205         ReturnTo string `json:"return_to"` // Redirect to this URL after logging out
206 }
207
208 type API interface {
209         ConfigGet(ctx context.Context) (json.RawMessage, error)
210         Login(ctx context.Context, options LoginOptions) (LoginResponse, error)
211         Logout(ctx context.Context, options LogoutOptions) (LogoutResponse, error)
212         CollectionCreate(ctx context.Context, options CreateOptions) (Collection, error)
213         CollectionUpdate(ctx context.Context, options UpdateOptions) (Collection, error)
214         CollectionGet(ctx context.Context, options GetOptions) (Collection, error)
215         CollectionList(ctx context.Context, options ListOptions) (CollectionList, error)
216         CollectionProvenance(ctx context.Context, options GetOptions) (map[string]interface{}, error)
217         CollectionUsedBy(ctx context.Context, options GetOptions) (map[string]interface{}, error)
218         CollectionDelete(ctx context.Context, options DeleteOptions) (Collection, error)
219         CollectionTrash(ctx context.Context, options DeleteOptions) (Collection, error)
220         CollectionUntrash(ctx context.Context, options UntrashOptions) (Collection, error)
221         ContainerCreate(ctx context.Context, options CreateOptions) (Container, error)
222         ContainerUpdate(ctx context.Context, options UpdateOptions) (Container, error)
223         ContainerGet(ctx context.Context, options GetOptions) (Container, error)
224         ContainerList(ctx context.Context, options ListOptions) (ContainerList, error)
225         ContainerDelete(ctx context.Context, options DeleteOptions) (Container, error)
226         ContainerLock(ctx context.Context, options GetOptions) (Container, error)
227         ContainerUnlock(ctx context.Context, options GetOptions) (Container, error)
228         ContainerSSH(ctx context.Context, options ContainerSSHOptions) (ContainerSSHConnection, error)
229         ContainerRequestCreate(ctx context.Context, options CreateOptions) (ContainerRequest, error)
230         ContainerRequestUpdate(ctx context.Context, options UpdateOptions) (ContainerRequest, error)
231         ContainerRequestGet(ctx context.Context, options GetOptions) (ContainerRequest, error)
232         ContainerRequestList(ctx context.Context, options ListOptions) (ContainerRequestList, error)
233         ContainerRequestDelete(ctx context.Context, options DeleteOptions) (ContainerRequest, error)
234         GroupCreate(ctx context.Context, options CreateOptions) (Group, error)
235         GroupUpdate(ctx context.Context, options UpdateOptions) (Group, error)
236         GroupGet(ctx context.Context, options GetOptions) (Group, error)
237         GroupList(ctx context.Context, options ListOptions) (GroupList, error)
238         GroupContents(ctx context.Context, options GroupContentsOptions) (ObjectList, error)
239         GroupShared(ctx context.Context, options ListOptions) (GroupList, error)
240         GroupDelete(ctx context.Context, options DeleteOptions) (Group, error)
241         GroupTrash(ctx context.Context, options DeleteOptions) (Group, error)
242         GroupUntrash(ctx context.Context, options UntrashOptions) (Group, error)
243         SpecimenCreate(ctx context.Context, options CreateOptions) (Specimen, error)
244         SpecimenUpdate(ctx context.Context, options UpdateOptions) (Specimen, error)
245         SpecimenGet(ctx context.Context, options GetOptions) (Specimen, error)
246         SpecimenList(ctx context.Context, options ListOptions) (SpecimenList, error)
247         SpecimenDelete(ctx context.Context, options DeleteOptions) (Specimen, error)
248         UserCreate(ctx context.Context, options CreateOptions) (User, error)
249         UserUpdate(ctx context.Context, options UpdateOptions) (User, error)
250         UserUpdateUUID(ctx context.Context, options UpdateUUIDOptions) (User, error)
251         UserMerge(ctx context.Context, options UserMergeOptions) (User, error)
252         UserActivate(ctx context.Context, options UserActivateOptions) (User, error)
253         UserSetup(ctx context.Context, options UserSetupOptions) (map[string]interface{}, error)
254         UserUnsetup(ctx context.Context, options GetOptions) (User, error)
255         UserGet(ctx context.Context, options GetOptions) (User, error)
256         UserGetCurrent(ctx context.Context, options GetOptions) (User, error)
257         UserGetSystem(ctx context.Context, options GetOptions) (User, error)
258         UserList(ctx context.Context, options ListOptions) (UserList, error)
259         UserDelete(ctx context.Context, options DeleteOptions) (User, error)
260         UserBatchUpdate(context.Context, UserBatchUpdateOptions) (UserList, error)
261         UserAuthenticate(ctx context.Context, options UserAuthenticateOptions) (APIClientAuthorization, error)
262         APIClientAuthorizationCurrent(ctx context.Context, options GetOptions) (APIClientAuthorization, error)
263 }