1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
19 "git.curoverse.com/arvados.git/sdk/go/arvados"
22 type TokenProvider func(context.Context) ([]string, error)
26 httpClient http.Client
28 tokenProvider TokenProvider
31 func NewConn(clusterID string, url *url.URL, insecure bool, tp TokenProvider) *Conn {
32 transport := http.DefaultTransport
34 // It's not safe to copy *http.DefaultTransport
35 // because it has a mutex (which might be locked)
36 // protecting a private map (which might not be nil).
37 // So we build our own, using the Go 1.12 default
38 // values, ignoring any changes the application has
39 // made to http.DefaultTransport.
40 transport = &http.Transport{
41 DialContext: (&net.Dialer{
42 Timeout: 30 * time.Second,
43 KeepAlive: 30 * time.Second,
47 IdleConnTimeout: 90 * time.Second,
48 TLSHandshakeTimeout: 10 * time.Second,
49 ExpectContinueTimeout: 1 * time.Second,
50 TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
55 httpClient: http.Client{Transport: transport},
61 func (conn *Conn) requestAndDecode(ctx context.Context, dst interface{}, ep arvados.APIEndpoint, body io.Reader, opts interface{}) error {
62 aClient := arvados.Client{
63 Client: &conn.httpClient,
64 Scheme: conn.baseURL.Scheme,
65 APIHost: conn.baseURL.Host,
67 tokens, err := conn.tokenProvider(ctx)
70 } else if len(tokens) > 0 {
71 ctx = arvados.ContextWithAuthorization(ctx, "Bearer "+tokens[0])
73 // Use a non-empty auth string to ensure we override
74 // any default token set on aClient -- and to avoid
75 // having the remote prompt us to send a token by
77 ctx = arvados.ContextWithAuthorization(ctx, "Bearer -")
80 // Encode opts to JSON and decode from there to a
81 // map[string]interface{}, so we can munge the query params
82 // using the JSON key names specified by opts' struct tags.
83 j, err := json.Marshal(opts)
85 return fmt.Errorf("%T: requestAndDecode: Marshal opts: %s", conn, err)
87 var params map[string]interface{}
88 err = json.Unmarshal(j, ¶ms)
90 return fmt.Errorf("%T: requestAndDecode: Unmarshal opts: %s", conn, err)
92 if attrs, ok := params["attrs"]; ok && ep.AttrsKey != "" {
93 params[ep.AttrsKey] = attrs
94 delete(params, "attrs")
96 if limit, ok := params["limit"].(float64); ok && limit < 0 {
97 // Negative limit means "not specified" here, but some
98 // servers/versions do not accept that, so we need to
99 // remove it entirely.
100 delete(params, "limit")
103 params["reader_tokens"] = tokens[1:]
106 if strings.Contains(ep.Path, "/:uuid") {
107 uuid, _ := params["uuid"].(string)
108 path = strings.Replace(path, "/:uuid", "/"+uuid, 1)
109 delete(params, "uuid")
111 return aClient.RequestAndDecodeContext(ctx, dst, ep.Method, path, body, params)
114 func (conn *Conn) CollectionCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Collection, error) {
115 ep := arvados.EndpointCollectionCreate
116 var resp arvados.Collection
117 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
121 func (conn *Conn) CollectionUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Collection, error) {
122 ep := arvados.EndpointCollectionUpdate
123 var resp arvados.Collection
124 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
128 func (conn *Conn) CollectionGet(ctx context.Context, options arvados.GetOptions) (arvados.Collection, error) {
129 ep := arvados.EndpointCollectionGet
130 var resp arvados.Collection
131 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
135 func (conn *Conn) CollectionList(ctx context.Context, options arvados.ListOptions) (arvados.CollectionList, error) {
136 ep := arvados.EndpointCollectionList
137 var resp arvados.CollectionList
138 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
142 func (conn *Conn) CollectionProvenance(ctx context.Context, options arvados.GetOptions) (map[string]interface{}, error) {
143 ep := arvados.EndpointCollectionProvenance
144 var resp map[string]interface{}
145 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
149 func (conn *Conn) CollectionUsedBy(ctx context.Context, options arvados.GetOptions) (map[string]interface{}, error) {
150 ep := arvados.EndpointCollectionUsedBy
151 var resp map[string]interface{}
152 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
156 func (conn *Conn) CollectionDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Collection, error) {
157 ep := arvados.EndpointCollectionDelete
158 var resp arvados.Collection
159 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
163 func (conn *Conn) CollectionTrash(ctx context.Context, options arvados.DeleteOptions) (arvados.Collection, error) {
164 ep := arvados.EndpointCollectionTrash
165 var resp arvados.Collection
166 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
170 func (conn *Conn) CollectionUntrash(ctx context.Context, options arvados.UntrashOptions) (arvados.Collection, error) {
171 ep := arvados.EndpointCollectionUntrash
172 var resp arvados.Collection
173 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
177 func (conn *Conn) ContainerCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Container, error) {
178 ep := arvados.EndpointContainerCreate
179 var resp arvados.Container
180 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
184 func (conn *Conn) ContainerUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Container, error) {
185 ep := arvados.EndpointContainerUpdate
186 var resp arvados.Container
187 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
191 func (conn *Conn) ContainerGet(ctx context.Context, options arvados.GetOptions) (arvados.Container, error) {
192 ep := arvados.EndpointContainerGet
193 var resp arvados.Container
194 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
198 func (conn *Conn) ContainerList(ctx context.Context, options arvados.ListOptions) (arvados.ContainerList, error) {
199 ep := arvados.EndpointContainerList
200 var resp arvados.ContainerList
201 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
205 func (conn *Conn) ContainerDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Container, error) {
206 ep := arvados.EndpointContainerDelete
207 var resp arvados.Container
208 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
212 func (conn *Conn) ContainerLock(ctx context.Context, options arvados.GetOptions) (arvados.Container, error) {
213 ep := arvados.EndpointContainerLock
214 var resp arvados.Container
215 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
219 func (conn *Conn) ContainerUnlock(ctx context.Context, options arvados.GetOptions) (arvados.Container, error) {
220 ep := arvados.EndpointContainerUnlock
221 var resp arvados.Container
222 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
226 func (conn *Conn) SpecimenCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Specimen, error) {
227 ep := arvados.EndpointSpecimenCreate
228 var resp arvados.Specimen
229 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
233 func (conn *Conn) SpecimenUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Specimen, error) {
234 ep := arvados.EndpointSpecimenUpdate
235 var resp arvados.Specimen
236 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
240 func (conn *Conn) SpecimenGet(ctx context.Context, options arvados.GetOptions) (arvados.Specimen, error) {
241 ep := arvados.EndpointSpecimenGet
242 var resp arvados.Specimen
243 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
247 func (conn *Conn) SpecimenList(ctx context.Context, options arvados.ListOptions) (arvados.SpecimenList, error) {
248 ep := arvados.EndpointSpecimenList
249 var resp arvados.SpecimenList
250 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
254 func (conn *Conn) SpecimenDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Specimen, error) {
255 ep := arvados.EndpointSpecimenDelete
256 var resp arvados.Specimen
257 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
261 func (conn *Conn) APIClientAuthorizationCurrent(ctx context.Context, options arvados.GetOptions) (arvados.APIClientAuthorization, error) {
262 ep := arvados.EndpointAPIClientAuthorizationCurrent
263 var resp arvados.APIClientAuthorization
264 err := conn.requestAndDecode(ctx, &resp, ep, nil, options)