1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
24 "git.arvados.org/arvados.git/sdk/go/arvados"
25 "git.arvados.org/arvados.git/sdk/go/auth"
26 "git.arvados.org/arvados.git/sdk/go/ctxlog"
27 "git.arvados.org/arvados.git/sdk/go/httpserver"
30 const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
32 type TokenProvider func(context.Context) ([]string, error)
34 func PassthroughTokenProvider(ctx context.Context) ([]string, error) {
35 incoming, ok := auth.FromContext(ctx)
37 return nil, errors.New("no token provided")
39 return incoming.Tokens, nil
43 SendHeader http.Header
44 RedactHostInErrors bool
47 httpClient http.Client
49 tokenProvider TokenProvider
52 func NewConn(clusterID string, url *url.URL, insecure bool, tp TokenProvider) *Conn {
53 transport := http.DefaultTransport
55 // It's not safe to copy *http.DefaultTransport
56 // because it has a mutex (which might be locked)
57 // protecting a private map (which might not be nil).
58 // So we build our own, using the Go 1.12 default
59 // values, ignoring any changes the application has
60 // made to http.DefaultTransport.
61 transport = &http.Transport{
62 DialContext: (&net.Dialer{
63 Timeout: 30 * time.Second,
64 KeepAlive: 30 * time.Second,
68 IdleConnTimeout: 90 * time.Second,
69 TLSHandshakeTimeout: 10 * time.Second,
70 ExpectContinueTimeout: 1 * time.Second,
71 TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
76 httpClient: http.Client{
77 CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse },
85 func (conn *Conn) requestAndDecode(ctx context.Context, dst interface{}, ep arvados.APIEndpoint, body io.Reader, opts interface{}) error {
86 aClient := arvados.Client{
87 Client: &conn.httpClient,
88 Scheme: conn.baseURL.Scheme,
89 APIHost: conn.baseURL.Host,
90 SendHeader: conn.SendHeader,
92 tokens, err := conn.tokenProvider(ctx)
95 } else if len(tokens) > 0 {
96 ctx = arvados.ContextWithAuthorization(ctx, "Bearer "+tokens[0])
98 // Use a non-empty auth string to ensure we override
99 // any default token set on aClient -- and to avoid
100 // having the remote prompt us to send a token by
102 ctx = arvados.ContextWithAuthorization(ctx, "Bearer -")
105 // Encode opts to JSON and decode from there to a
106 // map[string]interface{}, so we can munge the query params
107 // using the JSON key names specified by opts' struct tags.
108 j, err := json.Marshal(opts)
110 return fmt.Errorf("%T: requestAndDecode: Marshal opts: %s", conn, err)
112 var params map[string]interface{}
113 dec := json.NewDecoder(bytes.NewBuffer(j))
115 err = dec.Decode(¶ms)
117 return fmt.Errorf("%T: requestAndDecode: Decode opts: %s", conn, err)
119 if attrs, ok := params["attrs"]; ok && ep.AttrsKey != "" {
120 params[ep.AttrsKey] = attrs
121 delete(params, "attrs")
123 if limitStr, ok := params["limit"]; ok {
124 if limit, err := strconv.ParseInt(string(limitStr.(json.Number)), 10, 64); err == nil && limit < 0 {
125 // Negative limit means "not specified" here, but some
126 // servers/versions do not accept that, so we need to
127 // remove it entirely.
128 delete(params, "limit")
132 if authinfo, ok := params["auth_info"]; ok {
133 if tmp, ok2 := authinfo.(map[string]interface{}); ok2 {
134 for k, v := range tmp {
135 if strings.HasSuffix(k, "_at") {
136 // Change zero times values to nil
137 if v, ok3 := v.(string); ok3 && (strings.HasPrefix(v, "0001-01-01T00:00:00") || v == "") {
146 params["reader_tokens"] = tokens[1:]
149 if strings.Contains(ep.Path, "/{uuid}") {
150 uuid, _ := params["uuid"].(string)
151 path = strings.Replace(path, "/{uuid}", "/"+uuid, 1)
152 delete(params, "uuid")
154 err = aClient.RequestAndDecodeContext(ctx, dst, ep.Method, path, body, params)
155 if err != nil && conn.RedactHostInErrors {
156 redacted := strings.Replace(err.Error(), strings.TrimSuffix(conn.baseURL.String(), "/"), "//railsapi.internal", -1)
157 if strings.HasPrefix(redacted, "request failed: ") {
158 redacted = strings.Replace(redacted, "request failed: ", "", -1)
160 if redacted != err.Error() {
161 if err, ok := err.(httpStatusError); ok {
162 return wrapHTTPStatusError(err, redacted)
164 return errors.New(redacted)
171 func (conn *Conn) BaseURL() url.URL {
175 func (conn *Conn) ConfigGet(ctx context.Context) (json.RawMessage, error) {
176 ep := arvados.EndpointConfigGet
177 var resp json.RawMessage
178 err := conn.requestAndDecode(ctx, &resp, ep, nil, nil)
182 func (conn *Conn) VocabularyGet(ctx context.Context) (arvados.Vocabulary, error) {
183 ep := arvados.EndpointVocabularyGet
184 var resp arvados.Vocabulary
185 err := conn.requestAndDecode(ctx, &resp, ep, nil, nil)
189 func (conn *Conn) Login(ctx context.Context, options arvados.LoginOptions) (arvados.LoginResponse, error) {
190 ep := arvados.EndpointLogin
191 var resp arvados.LoginResponse
192 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
193 resp.RedirectLocation = conn.relativeToBaseURL(resp.RedirectLocation)
197 func (conn *Conn) Logout(ctx context.Context, options arvados.LogoutOptions) (arvados.LogoutResponse, error) {
198 ep := arvados.EndpointLogout
199 var resp arvados.LogoutResponse
200 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
201 resp.RedirectLocation = conn.relativeToBaseURL(resp.RedirectLocation)
205 // If the given location is a valid URL and its origin is the same as
206 // conn.baseURL, return it as a relative URL. Otherwise, return it
208 func (conn *Conn) relativeToBaseURL(location string) string {
209 u, err := url.Parse(location)
210 if err == nil && u.Scheme == conn.baseURL.Scheme && strings.ToLower(u.Host) == strings.ToLower(conn.baseURL.Host) {
220 func (conn *Conn) CollectionCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Collection, error) {
221 ep := arvados.EndpointCollectionCreate
222 var resp arvados.Collection
223 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
227 func (conn *Conn) CollectionUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Collection, error) {
228 ep := arvados.EndpointCollectionUpdate
229 var resp arvados.Collection
230 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
234 func (conn *Conn) CollectionGet(ctx context.Context, options arvados.GetOptions) (arvados.Collection, error) {
235 ep := arvados.EndpointCollectionGet
236 var resp arvados.Collection
237 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
241 func (conn *Conn) CollectionList(ctx context.Context, options arvados.ListOptions) (arvados.CollectionList, error) {
242 ep := arvados.EndpointCollectionList
243 var resp arvados.CollectionList
244 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
248 func (conn *Conn) CollectionProvenance(ctx context.Context, options arvados.GetOptions) (map[string]interface{}, error) {
249 ep := arvados.EndpointCollectionProvenance
250 var resp map[string]interface{}
251 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
255 func (conn *Conn) CollectionUsedBy(ctx context.Context, options arvados.GetOptions) (map[string]interface{}, error) {
256 ep := arvados.EndpointCollectionUsedBy
257 var resp map[string]interface{}
258 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
262 func (conn *Conn) CollectionDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Collection, error) {
263 ep := arvados.EndpointCollectionDelete
264 var resp arvados.Collection
265 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
269 func (conn *Conn) CollectionTrash(ctx context.Context, options arvados.DeleteOptions) (arvados.Collection, error) {
270 ep := arvados.EndpointCollectionTrash
271 var resp arvados.Collection
272 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
276 func (conn *Conn) CollectionUntrash(ctx context.Context, options arvados.UntrashOptions) (arvados.Collection, error) {
277 ep := arvados.EndpointCollectionUntrash
278 var resp arvados.Collection
279 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
283 func (conn *Conn) ContainerCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Container, error) {
284 ep := arvados.EndpointContainerCreate
285 var resp arvados.Container
286 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
290 func (conn *Conn) ContainerUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Container, error) {
291 ep := arvados.EndpointContainerUpdate
292 var resp arvados.Container
293 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
297 func (conn *Conn) ContainerPriorityUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Container, error) {
298 ep := arvados.EndpointContainerPriorityUpdate
299 var resp arvados.Container
300 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
304 func (conn *Conn) ContainerGet(ctx context.Context, options arvados.GetOptions) (arvados.Container, error) {
305 ep := arvados.EndpointContainerGet
306 var resp arvados.Container
307 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
311 func (conn *Conn) ContainerList(ctx context.Context, options arvados.ListOptions) (arvados.ContainerList, error) {
312 ep := arvados.EndpointContainerList
313 var resp arvados.ContainerList
314 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
318 func (conn *Conn) ContainerDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Container, error) {
319 ep := arvados.EndpointContainerDelete
320 var resp arvados.Container
321 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
325 func (conn *Conn) ContainerLock(ctx context.Context, options arvados.GetOptions) (arvados.Container, error) {
326 ep := arvados.EndpointContainerLock
327 var resp arvados.Container
328 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
332 func (conn *Conn) ContainerUnlock(ctx context.Context, options arvados.GetOptions) (arvados.Container, error) {
333 ep := arvados.EndpointContainerUnlock
334 var resp arvados.Container
335 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
339 // ContainerSSH returns a connection to the out-of-band SSH server for
340 // a running container. If the returned error is nil, the caller is
341 // responsible for closing sshconn.Conn.
342 func (conn *Conn) ContainerSSH(ctx context.Context, options arvados.ContainerSSHOptions) (sshconn arvados.ConnectionResponse, err error) {
343 u, err := conn.baseURL.Parse("/" + strings.Replace(arvados.EndpointContainerSSH.Path, "{uuid}", options.UUID, -1))
345 err = fmt.Errorf("url.Parse: %w", err)
348 return conn.socket(ctx, u, "ssh", url.Values{
349 "detach_keys": {options.DetachKeys},
350 "login_username": {options.LoginUsername},
351 "no_forward": {fmt.Sprintf("%v", options.NoForward)},
355 // ContainerGatewayTunnel returns a connection to a yamux session on
356 // the controller. The caller should connect the returned resp.Conn to
357 // a client-side yamux session.
358 func (conn *Conn) ContainerGatewayTunnel(ctx context.Context, options arvados.ContainerGatewayTunnelOptions) (tunnelconn arvados.ConnectionResponse, err error) {
359 u, err := conn.baseURL.Parse("/" + strings.Replace(arvados.EndpointContainerGatewayTunnel.Path, "{uuid}", options.UUID, -1))
361 err = fmt.Errorf("url.Parse: %w", err)
364 return conn.socket(ctx, u, "tunnel", url.Values{
365 "auth_secret": {options.AuthSecret},
369 // socket sets up a socket using the specified API endpoint and
371 func (conn *Conn) socket(ctx context.Context, u *url.URL, upgradeHeader string, postform url.Values) (connresp arvados.ConnectionResponse, err error) {
372 addr := conn.baseURL.Host
373 if strings.Index(addr, ":") < 1 || (strings.Contains(addr, "::") && addr[0] != '[') {
374 // hostname or ::1 or 1::1
375 addr = net.JoinHostPort(addr, "https")
378 if tlsconf := conn.httpClient.Transport.(*http.Transport).TLSClientConfig; tlsconf != nil && tlsconf.InsecureSkipVerify {
381 netconn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: insecure})
383 return connresp, fmt.Errorf("tls.Dial: %w", err)
390 bufr := bufio.NewReader(netconn)
391 bufw := bufio.NewWriter(netconn)
393 tokens, err := conn.tokenProvider(ctx)
396 } else if len(tokens) < 1 {
397 return connresp, httpserver.ErrorWithStatus(errors.New("unauthorized"), http.StatusUnauthorized)
399 postdata := postform.Encode()
400 bufw.WriteString("POST " + u.String() + " HTTP/1.1\r\n")
401 bufw.WriteString("Authorization: Bearer " + tokens[0] + "\r\n")
402 bufw.WriteString("Host: " + u.Host + "\r\n")
403 bufw.WriteString("Upgrade: " + upgradeHeader + "\r\n")
404 bufw.WriteString("Content-Type: application/x-www-form-urlencoded\r\n")
405 fmt.Fprintf(bufw, "Content-Length: %d\r\n", len(postdata))
406 bufw.WriteString("\r\n")
407 bufw.WriteString(postdata)
409 resp, err := http.ReadResponse(bufr, &http.Request{Method: "POST"})
411 return connresp, fmt.Errorf("http.ReadResponse: %w", err)
413 defer resp.Body.Close()
414 if resp.StatusCode != http.StatusSwitchingProtocols {
415 ctxlog.FromContext(ctx).Infof("rpc.Conn.socket: server %s did not switch protocols, got status %s", u.String(), resp.Status)
416 body, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 10000))
418 var errDoc httpserver.ErrorResponse
419 if err := json.Unmarshal(body, &errDoc); err == nil {
420 message = strings.Join(errDoc.Errors, "; ")
422 message = fmt.Sprintf("%q", body)
424 return connresp, fmt.Errorf("server did not provide a tunnel: %s: %s", resp.Status, message)
426 if strings.ToLower(resp.Header.Get("Upgrade")) != upgradeHeader ||
427 strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
428 return connresp, fmt.Errorf("bad response from server: Upgrade %q Connection %q", resp.Header.Get("Upgrade"), resp.Header.Get("Connection"))
430 connresp.Conn = netconn
431 connresp.Bufrw = &bufio.ReadWriter{Reader: bufr, Writer: bufw}
432 connresp.Header = resp.Header
436 func (conn *Conn) ContainerRequestCreate(ctx context.Context, options arvados.CreateOptions) (arvados.ContainerRequest, error) {
437 ep := arvados.EndpointContainerRequestCreate
438 var resp arvados.ContainerRequest
439 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
443 func (conn *Conn) ContainerRequestUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.ContainerRequest, error) {
444 ep := arvados.EndpointContainerRequestUpdate
445 var resp arvados.ContainerRequest
446 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
450 func (conn *Conn) ContainerRequestGet(ctx context.Context, options arvados.GetOptions) (arvados.ContainerRequest, error) {
451 ep := arvados.EndpointContainerRequestGet
452 var resp arvados.ContainerRequest
453 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
457 func (conn *Conn) ContainerRequestList(ctx context.Context, options arvados.ListOptions) (arvados.ContainerRequestList, error) {
458 ep := arvados.EndpointContainerRequestList
459 var resp arvados.ContainerRequestList
460 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
464 func (conn *Conn) ContainerRequestDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.ContainerRequest, error) {
465 ep := arvados.EndpointContainerRequestDelete
466 var resp arvados.ContainerRequest
467 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
471 func (conn *Conn) GroupCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Group, error) {
472 ep := arvados.EndpointGroupCreate
473 var resp arvados.Group
474 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
478 func (conn *Conn) GroupUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Group, error) {
479 ep := arvados.EndpointGroupUpdate
480 var resp arvados.Group
481 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
485 func (conn *Conn) GroupGet(ctx context.Context, options arvados.GetOptions) (arvados.Group, error) {
486 ep := arvados.EndpointGroupGet
487 var resp arvados.Group
488 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
492 func (conn *Conn) GroupList(ctx context.Context, options arvados.ListOptions) (arvados.GroupList, error) {
493 ep := arvados.EndpointGroupList
494 var resp arvados.GroupList
495 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
499 func (conn *Conn) GroupContents(ctx context.Context, options arvados.GroupContentsOptions) (arvados.ObjectList, error) {
500 ep := arvados.EndpointGroupContents
501 var resp arvados.ObjectList
502 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
506 func (conn *Conn) GroupShared(ctx context.Context, options arvados.ListOptions) (arvados.GroupList, error) {
507 ep := arvados.EndpointGroupShared
508 var resp arvados.GroupList
509 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
513 func (conn *Conn) GroupDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Group, error) {
514 ep := arvados.EndpointGroupDelete
515 var resp arvados.Group
516 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
520 func (conn *Conn) GroupTrash(ctx context.Context, options arvados.DeleteOptions) (arvados.Group, error) {
521 ep := arvados.EndpointGroupTrash
522 var resp arvados.Group
523 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
527 func (conn *Conn) GroupUntrash(ctx context.Context, options arvados.UntrashOptions) (arvados.Group, error) {
528 ep := arvados.EndpointGroupUntrash
529 var resp arvados.Group
530 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
534 func (conn *Conn) LinkCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Link, error) {
535 ep := arvados.EndpointLinkCreate
536 var resp arvados.Link
537 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
541 func (conn *Conn) LinkUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Link, error) {
542 ep := arvados.EndpointLinkUpdate
543 var resp arvados.Link
544 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
548 func (conn *Conn) LinkGet(ctx context.Context, options arvados.GetOptions) (arvados.Link, error) {
549 ep := arvados.EndpointLinkGet
550 var resp arvados.Link
551 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
555 func (conn *Conn) LinkList(ctx context.Context, options arvados.ListOptions) (arvados.LinkList, error) {
556 ep := arvados.EndpointLinkList
557 var resp arvados.LinkList
558 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
562 func (conn *Conn) LinkDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Link, error) {
563 ep := arvados.EndpointLinkDelete
564 var resp arvados.Link
565 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
569 func (conn *Conn) LogCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Log, error) {
570 ep := arvados.EndpointLogCreate
572 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
576 func (conn *Conn) LogUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Log, error) {
577 ep := arvados.EndpointLogUpdate
579 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
583 func (conn *Conn) LogGet(ctx context.Context, options arvados.GetOptions) (arvados.Log, error) {
584 ep := arvados.EndpointLogGet
586 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
590 func (conn *Conn) LogList(ctx context.Context, options arvados.ListOptions) (arvados.LogList, error) {
591 ep := arvados.EndpointLogList
592 var resp arvados.LogList
593 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
597 func (conn *Conn) LogDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Log, error) {
598 ep := arvados.EndpointLogDelete
600 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
604 func (conn *Conn) SpecimenCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Specimen, error) {
605 ep := arvados.EndpointSpecimenCreate
606 var resp arvados.Specimen
607 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
611 func (conn *Conn) SpecimenUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Specimen, error) {
612 ep := arvados.EndpointSpecimenUpdate
613 var resp arvados.Specimen
614 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
618 func (conn *Conn) SpecimenGet(ctx context.Context, options arvados.GetOptions) (arvados.Specimen, error) {
619 ep := arvados.EndpointSpecimenGet
620 var resp arvados.Specimen
621 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
625 func (conn *Conn) SpecimenList(ctx context.Context, options arvados.ListOptions) (arvados.SpecimenList, error) {
626 ep := arvados.EndpointSpecimenList
627 var resp arvados.SpecimenList
628 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
632 func (conn *Conn) SpecimenDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Specimen, error) {
633 ep := arvados.EndpointSpecimenDelete
634 var resp arvados.Specimen
635 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
639 func (conn *Conn) SysTrashSweep(ctx context.Context, options struct{}) (struct{}, error) {
640 ep := arvados.EndpointSysTrashSweep
642 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
646 func (conn *Conn) UserCreate(ctx context.Context, options arvados.CreateOptions) (arvados.User, error) {
647 ep := arvados.EndpointUserCreate
648 var resp arvados.User
649 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
652 func (conn *Conn) UserUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.User, error) {
653 ep := arvados.EndpointUserUpdate
654 var resp arvados.User
655 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
658 func (conn *Conn) UserMerge(ctx context.Context, options arvados.UserMergeOptions) (arvados.User, error) {
659 ep := arvados.EndpointUserMerge
660 var resp arvados.User
661 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
664 func (conn *Conn) UserActivate(ctx context.Context, options arvados.UserActivateOptions) (arvados.User, error) {
665 ep := arvados.EndpointUserActivate
666 var resp arvados.User
667 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
670 func (conn *Conn) UserSetup(ctx context.Context, options arvados.UserSetupOptions) (map[string]interface{}, error) {
671 ep := arvados.EndpointUserSetup
672 var resp map[string]interface{}
673 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
676 func (conn *Conn) UserUnsetup(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
677 ep := arvados.EndpointUserUnsetup
678 var resp arvados.User
679 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
682 func (conn *Conn) UserGet(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
683 ep := arvados.EndpointUserGet
684 var resp arvados.User
685 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
688 func (conn *Conn) UserGetCurrent(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
689 ep := arvados.EndpointUserGetCurrent
690 var resp arvados.User
691 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
694 func (conn *Conn) UserGetSystem(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
695 ep := arvados.EndpointUserGetSystem
696 var resp arvados.User
697 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
700 func (conn *Conn) UserList(ctx context.Context, options arvados.ListOptions) (arvados.UserList, error) {
701 ep := arvados.EndpointUserList
702 var resp arvados.UserList
703 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
706 func (conn *Conn) UserDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.User, error) {
707 ep := arvados.EndpointUserDelete
708 var resp arvados.User
709 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
713 func (conn *Conn) APIClientAuthorizationCurrent(ctx context.Context, options arvados.GetOptions) (arvados.APIClientAuthorization, error) {
714 ep := arvados.EndpointAPIClientAuthorizationCurrent
715 var resp arvados.APIClientAuthorization
716 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
719 func (conn *Conn) APIClientAuthorizationCreate(ctx context.Context, options arvados.CreateOptions) (arvados.APIClientAuthorization, error) {
720 ep := arvados.EndpointAPIClientAuthorizationCreate
721 var resp arvados.APIClientAuthorization
722 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
725 func (conn *Conn) APIClientAuthorizationUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.APIClientAuthorization, error) {
726 ep := arvados.EndpointAPIClientAuthorizationUpdate
727 var resp arvados.APIClientAuthorization
728 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
731 func (conn *Conn) APIClientAuthorizationDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.APIClientAuthorization, error) {
732 ep := arvados.EndpointAPIClientAuthorizationDelete
733 var resp arvados.APIClientAuthorization
734 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
737 func (conn *Conn) APIClientAuthorizationList(ctx context.Context, options arvados.ListOptions) (arvados.APIClientAuthorizationList, error) {
738 ep := arvados.EndpointAPIClientAuthorizationList
739 var resp arvados.APIClientAuthorizationList
740 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
743 func (conn *Conn) APIClientAuthorizationGet(ctx context.Context, options arvados.GetOptions) (arvados.APIClientAuthorization, error) {
744 ep := arvados.EndpointAPIClientAuthorizationGet
745 var resp arvados.APIClientAuthorization
746 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
750 type UserSessionAuthInfo struct {
751 UserUUID string `json:"user_uuid"`
752 Email string `json:"email"`
753 AlternateEmails []string `json:"alternate_emails"`
754 FirstName string `json:"first_name"`
755 LastName string `json:"last_name"`
756 Username string `json:"username"`
757 ExpiresAt time.Time `json:"expires_at"`
760 type UserSessionCreateOptions struct {
761 AuthInfo UserSessionAuthInfo `json:"auth_info"`
762 ReturnTo string `json:"return_to"`
765 func (conn *Conn) UserSessionCreate(ctx context.Context, options UserSessionCreateOptions) (arvados.LoginResponse, error) {
766 ep := arvados.APIEndpoint{Method: "POST", Path: "auth/controller/callback"}
767 var resp arvados.LoginResponse
768 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
772 func (conn *Conn) UserBatchUpdate(ctx context.Context, options arvados.UserBatchUpdateOptions) (arvados.UserList, error) {
773 ep := arvados.EndpointUserBatchUpdate
774 var resp arvados.UserList
775 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
779 func (conn *Conn) UserAuthenticate(ctx context.Context, options arvados.UserAuthenticateOptions) (arvados.APIClientAuthorization, error) {
780 ep := arvados.EndpointUserAuthenticate
781 var resp arvados.APIClientAuthorization
782 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
786 // httpStatusError is an error with an HTTP status code that can be
787 // propagated by lib/controller/router, etc.
788 type httpStatusError interface {
793 // wrappedHTTPStatusError is used to augment/replace an error message
794 // while preserving the HTTP status code indicated by the original
796 type wrappedHTTPStatusError struct {
801 func wrapHTTPStatusError(err httpStatusError, message string) httpStatusError {
802 return wrappedHTTPStatusError{err, message}
805 func (err wrappedHTTPStatusError) Error() string {