Merge branch '16997-sort-config-for-diff'
[arvados.git] / lib / controller / rpc / conn.go
index 9d64dc539af9a0697460284de8183a05e469f84b..19e2d32d2cb01979317fff7dd74a16d3842bfe0e 100644 (file)
@@ -23,7 +23,6 @@ import (
 
        "git.arvados.org/arvados.git/sdk/go/arvados"
        "git.arvados.org/arvados.git/sdk/go/auth"
-       "git.arvados.org/arvados.git/sdk/go/ctxlog"
        "git.arvados.org/arvados.git/sdk/go/httpserver"
 )
 
@@ -40,7 +39,9 @@ func PassthroughTokenProvider(ctx context.Context) ([]string, error) {
 }
 
 type Conn struct {
-       SendHeader    http.Header
+       SendHeader         http.Header
+       RedactHostInErrors bool
+
        clusterID     string
        httpClient    http.Client
        baseURL       url.URL
@@ -149,7 +150,21 @@ func (conn *Conn) requestAndDecode(ctx context.Context, dst interface{}, ep arva
                path = strings.Replace(path, "/{uuid}", "/"+uuid, 1)
                delete(params, "uuid")
        }
-       return aClient.RequestAndDecodeContext(ctx, dst, ep.Method, path, body, params)
+       err = aClient.RequestAndDecodeContext(ctx, dst, ep.Method, path, body, params)
+       if err != nil && conn.RedactHostInErrors {
+               redacted := strings.Replace(err.Error(), conn.baseURL.String(), "//railsapi.internal", -1)
+               if strings.HasPrefix(redacted, "request failed: ") {
+                       redacted = strings.Replace(redacted, "request failed: ", "", -1)
+               }
+               if redacted != err.Error() {
+                       if err, ok := err.(httpStatusError); ok {
+                               return wrapHTTPStatusError(err, redacted)
+                       } else {
+                               return errors.New(redacted)
+                       }
+               }
+       }
+       return err
 }
 
 func (conn *Conn) BaseURL() url.URL {
@@ -446,49 +461,9 @@ func (conn *Conn) GroupList(ctx context.Context, options arvados.ListOptions) (a
 }
 
 func (conn *Conn) GroupContents(ctx context.Context, options arvados.GroupContentsOptions) (arvados.ObjectList, error) {
-       // The requested UUID can be a user (virtual home project), which we just pass on to
-       // the API server.
-       if strings.Index(options.UUID, "j7d0g") != 6 {
-               ep := arvados.EndpointGroupContents
-               var resp arvados.ObjectList
-               err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
-               return resp, err
-       }
-
-       log := ctxlog.FromContext(ctx)
-       var resp arvados.ObjectList
-
-       // Get the group object
-       epGet := arvados.EndpointGroupGet
-       var respGroup arvados.Group
-       err := conn.requestAndDecode(ctx, &respGroup, epGet, nil, options)
-       if err != nil {
-               return resp, err
-       }
-
-       // If the group has groupClass 'filter', apply the filters before getting the contents.
-       if respGroup.GroupClass == "filter" {
-               if filters, ok := respGroup.Properties["filters"]; ok {
-                       for _, f := range filters.([]interface{}) {
-                               // f is supposed to be a []string
-                               tmp, ok2 := f.([]interface{})
-                               if !ok2 || len(tmp) < 3 {
-                                       log.Warnf("filter unparsable: %T, %+v, original field: %T, %+v\n", tmp, tmp, f, f)
-                                       continue
-                               }
-                               var filter arvados.Filter
-                               filter.Attr = tmp[0].(string)
-                               filter.Operator = tmp[1].(string)
-                               filter.Operand = tmp[2]
-                               options.Filters = append(options.Filters, filter)
-                       }
-               }
-               // Use the generic /groups/contents endpoint for filter groups
-               options.UUID = ""
-       }
-
        ep := arvados.EndpointGroupContents
-       err = conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       var resp arvados.ObjectList
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
        return resp, err
 }
 
@@ -670,3 +645,26 @@ func (conn *Conn) UserAuthenticate(ctx context.Context, options arvados.UserAuth
        err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
        return resp, err
 }
+
+// httpStatusError is an error with an HTTP status code that can be
+// propagated by lib/controller/router, etc.
+type httpStatusError interface {
+       error
+       HTTPStatus() int
+}
+
+// wrappedHTTPStatusError is used to augment/replace an error message
+// while preserving the HTTP status code indicated by the original
+// error.
+type wrappedHTTPStatusError struct {
+       httpStatusError
+       message string
+}
+
+func wrapHTTPStatusError(err httpStatusError, message string) httpStatusError {
+       return wrappedHTTPStatusError{err, message}
+}
+
+func (err wrappedHTTPStatusError) Error() string {
+       return err.message
+}