From 6ef1bc9b506557c3152f10e2e85c8f9c5035c5c5 Mon Sep 17 00:00:00 2001 From: Illyoung Choi Date: Tue, 10 Aug 2021 16:34:35 -0700 Subject: [PATCH 1/4] Implement ticket --- irods/connection/connection.go | 16 ++++++ irods/message/ticketadmin_request.go | 81 +++++++++++++++++++++++++++ irods/message/ticketadmin_response.go | 31 ++++++++++ irods/types/account.go | 48 ++++++++++++++-- 4 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 irods/message/ticketadmin_request.go create mode 100644 irods/message/ticketadmin_response.go diff --git a/irods/connection/connection.go b/irods/connection/connection.go index 49eefc7..797372f 100644 --- a/irods/connection/connection.go +++ b/irods/connection/connection.go @@ -103,6 +103,10 @@ func (conn *IRODSConnection) Connect() error { return err } + if conn.Account.UseTicket() { + conn.showTicket() + } + conn.connected = true return nil @@ -322,6 +326,18 @@ func (conn *IRODSConnection) loginPAM() error { return conn.loginNative(conn.generatedPasswordForPAM) } +func (conn *IRODSConnection) showTicket() error { + util.LogInfo("Submitting a ticket to obtain access") + + if len(conn.Account.Ticket) > 0 { + // show the ticket + ticketRequest := message.NewIRODSMessageTicketAdminRequest("session", conn.Account.Ticket) + ticketResult := message.IRODSMessageTicketAdminResponse{} + return conn.RequestAndCheck(ticketRequest, &ticketResult) + } + return nil +} + // Disconnect disconnects func (conn *IRODSConnection) disconnectNow() error { conn.connected = false diff --git a/irods/message/ticketadmin_request.go b/irods/message/ticketadmin_request.go new file mode 100644 index 0000000..ab00cf6 --- /dev/null +++ b/irods/message/ticketadmin_request.go @@ -0,0 +1,81 @@ +package message + +import ( + "encoding/xml" + + "github.com/cyverse/go-irodsclient/irods/common" +) + +// IRODSMessageTicketAdminRequest stores ticket admin request +type IRODSMessageTicketAdminRequest struct { + XMLName xml.Name `xml:"ticketAdminInp_PI"` + Action string `xml:"arg1"` // session, create + Ticket string `xml:"arg2"` // ticket number + Arg3 string `xml:"arg3"` + Arg4 string `xml:"arg4"` + Arg5 string `xml:"arg5"` + Arg6 string `xml:"arg6"` +} + +func NewIRODSMessageTicketAdminRequest(action string, ticket string, args ...string) *IRODSMessageTicketAdminRequest { + request := &IRODSMessageTicketAdminRequest{ + Action: action, + Ticket: ticket, + } + + if len(args) > 0 { + request.Arg3 = args[0] + } + + if len(args) > 1 { + request.Arg4 = args[1] + } + + if len(args) > 2 { + request.Arg5 = args[2] + } + + if len(args) > 3 { + request.Arg6 = args[3] + } + + return request +} + +// GetBytes returns byte array +func (msg *IRODSMessageTicketAdminRequest) GetBytes() ([]byte, error) { + xmlBytes, err := xml.Marshal(msg) + return xmlBytes, err +} + +// FromBytes returns struct from bytes +func (msg *IRODSMessageTicketAdminRequest) FromBytes(bytes []byte) error { + err := xml.Unmarshal(bytes, msg) + return err +} + +// GetMessage builds a message +func (msg *IRODSMessageTicketAdminRequest) GetMessage() (*IRODSMessage, error) { + bytes, err := msg.GetBytes() + if err != nil { + return nil, err + } + + msgBody := IRODSMessageBody{ + Type: RODS_MESSAGE_API_REQ_TYPE, + Message: bytes, + Error: nil, + Bs: nil, + IntInfo: int32(common.TICKET_ADMIN_AN), + } + + msgHeader, err := msgBody.BuildHeader() + if err != nil { + return nil, err + } + + return &IRODSMessage{ + Header: msgHeader, + Body: &msgBody, + }, nil +} diff --git a/irods/message/ticketadmin_response.go b/irods/message/ticketadmin_response.go new file mode 100644 index 0000000..d7bcf7f --- /dev/null +++ b/irods/message/ticketadmin_response.go @@ -0,0 +1,31 @@ +package message + +import ( + "fmt" + + "github.com/cyverse/go-irodsclient/irods/common" +) + +// IRODSMessageTicketAdminResponse stores ticket admin response +type IRODSMessageTicketAdminResponse struct { + // empty structure + Result int +} + +// CheckError returns error if server returned an error +func (msg *IRODSMessageTicketAdminResponse) CheckError() error { + if msg.Result < 0 { + return common.MakeIRODSError(common.ErrorCode(msg.Result)) + } + return nil +} + +// FromMessage returns struct from IRODSMessage +func (msg *IRODSMessageTicketAdminResponse) FromMessage(msgIn *IRODSMessage) error { + if msgIn.Body == nil { + return fmt.Errorf("Cannot create a struct from an empty body") + } + + msg.Result = int(msgIn.Body.IntInfo) + return nil +} diff --git a/irods/types/account.go b/irods/types/account.go index 6b77242..06158b6 100644 --- a/irods/types/account.go +++ b/irods/types/account.go @@ -23,6 +23,7 @@ type IRODSAccount struct { ProxyZone string ServerDN string Password string + Ticket string PamTTL int SSLConfiguration *IRODSSSLConfig } @@ -43,6 +44,29 @@ func CreateIRODSAccount(host string, port int, user string, zone string, ProxyZone: zone, ServerDN: serverDN, Password: password, + Ticket: "", + PamTTL: PamTTLDefault, + SSLConfiguration: nil, + }, nil +} + +// CreateIRODSAccountForTicket creates IRODSAccount +func CreateIRODSAccountForTicket(host string, port int, user string, zone string, + authScheme AuthScheme, password string, ticket string, + serverDN string) (*IRODSAccount, error) { + return &IRODSAccount{ + AuthenticationScheme: authScheme, + ClientServerNegotiation: false, + CSNegotiationPolicy: CSNegotiationRequireTCP, + Host: host, + Port: port, + ClientUser: user, + ClientZone: zone, + ProxyUser: user, + ProxyZone: zone, + ServerDN: serverDN, + Password: password, + Ticket: ticket, PamTTL: PamTTLDefault, SSLConfiguration: nil, }, nil @@ -139,6 +163,11 @@ func CreateIRODSAccountFromYAML(yamlBytes []byte) (*IRODSAccount, error) { proxyZone = val.(string) } + ticket := "" + if val, ok := proxyUser["ticket"]; ok { + ticket = val.(string) + } + // client user clientUser := make(map[interface{}]interface{}) if val, ok := y["client_user"]; ok { @@ -155,6 +184,10 @@ func CreateIRODSAccountFromYAML(yamlBytes []byte) (*IRODSAccount, error) { clientZone = val.(string) } + if val, ok := clientUser["ticket"]; ok { + ticket = val.(string) + } + // normal user user := make(map[interface{}]interface{}) if val, ok := y["user"]; ok { @@ -176,6 +209,10 @@ func CreateIRODSAccountFromYAML(yamlBytes []byte) (*IRODSAccount, error) { clientZone = proxyZone } + if val, ok := user["ticket"]; ok { + ticket = val.(string) + } + // PAM Configuration pamConfig := make(map[interface{}]interface{}) if val, ok := y["pam"]; ok { @@ -240,6 +277,7 @@ func CreateIRODSAccountFromYAML(yamlBytes []byte) (*IRODSAccount, error) { ProxyZone: proxyZone, ServerDN: serverDN, Password: proxyPassword, + Ticket: ticket, PamTTL: pamTTL, SSLConfiguration: irodsSSLConfig, }, nil @@ -252,10 +290,12 @@ func (account *IRODSAccount) SetSSLConfiguration(sslConf *IRODSSSLConfig) { // UseProxyAccess returns whether it uses proxy access or not func (account *IRODSAccount) UseProxyAccess() bool { - if len(account.ProxyUser) > 0 && len(account.ClientUser) > 0 && account.ProxyUser != account.ClientUser { - return true - } - return false + return len(account.ProxyUser) > 0 && len(account.ClientUser) > 0 && account.ProxyUser != account.ClientUser +} + +// UseTicket returns whether it uses ticket for access control +func (account *IRODSAccount) UseTicket() bool { + return len(account.Ticket) > 0 } // MaskSensitiveData returns IRODSAccount object with sensitive data masked From 8c599d25c4f03079d5f64ef38d55b26b3a4e4ba9 Mon Sep 17 00:00:00 2001 From: Illyoung Choi Date: Tue, 10 Aug 2021 18:17:31 -0700 Subject: [PATCH 2/4] Do not use poorman transaction for ticket access --- irods/session/session.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/irods/session/session.go b/irods/session/session.go index a438a7c..2e4f105 100644 --- a/irods/session/session.go +++ b/irods/session/session.go @@ -68,6 +68,11 @@ func (sess *IRODSSession) AcquireConnection() (*connection.IRODSConnection, erro conn := v.(*connection.IRODSConnection) + if len(sess.Account.Ticket) > 0 { + // when ticket is used, we cannot use transaction since we don't have access to home dir + return conn, nil + } + if sess.Config.StartNewTransaction { // Each irods connection automatically starts a database transaction at initial setup. // All queries against irods using a connection will give results corresponding to the time From 5c97981cdb93bd4bbbb04e8461224fe27a0bdb7a Mon Sep 17 00:00:00 2001 From: Illyoung Choi Date: Wed, 11 Aug 2021 13:58:25 -0700 Subject: [PATCH 3/4] Refactor error handling --- irods/common/error_code.go | 10 --- irods/fs/collection.go | 55 +++++++++++++++ irods/fs/data_object.go | 90 ++++++++++++++++++++++++ irods/fs/resource.go | 13 ++-- irods/fs/usergroup.go | 84 ++++++++++++++++++++-- irods/message/admin_response.go | 3 +- irods/message/auth_result.go | 3 +- irods/message/closeobj_response.go | 3 +- irods/message/cpobj_response.go | 3 +- irods/message/createobj_response.go | 3 +- irods/message/cs_negotiation.go | 2 +- irods/message/endtransaction_response.go | 3 +- irods/message/filestat_response.go | 15 ++++ irods/message/mkcol_response.go | 3 +- irods/message/modaccess_response.go | 3 +- irods/message/modcol_response.go | 3 +- irods/message/modmeta_response.go | 3 +- irods/message/mvcol_response.go | 3 +- irods/message/mvobj_response.go | 3 +- irods/message/openobj_response.go | 3 +- irods/message/query_result.go | 15 ++++ irods/message/readobj_response.go | 3 +- irods/message/replobj_response.go | 3 +- irods/message/rmcol_response.go | 3 +- irods/message/rmobj_response.go | 3 +- irods/message/seekobj_response.go | 3 +- irods/message/ticketadmin_response.go | 3 +- irods/message/trimobj_response.go | 3 +- irods/message/truncobj_response.go | 3 +- irods/message/useradmin_response.go | 3 +- irods/message/version.go | 2 +- irods/message/writeobj_response.go | 3 +- irods/types/account.go | 2 +- irods/types/error.go | 64 +++++++++++++++++ 34 files changed, 374 insertions(+), 47 deletions(-) create mode 100644 irods/types/error.go diff --git a/irods/common/error_code.go b/irods/common/error_code.go index f074b9b..879559e 100644 --- a/irods/common/error_code.go +++ b/irods/common/error_code.go @@ -910,13 +910,3 @@ func GetIRODSErrorString(code ErrorCode) string { } return fmt.Sprintf("ErrorCode: %d", int(code)) } - -// MakeIRODSError creates an error from error code -func MakeIRODSError(code ErrorCode) error { - return fmt.Errorf("iRODS Error - %d (%s)", int(code), GetIRODSErrorString(code)) -} - -// MakeIRODSErrorFromString creates an error from error code and message -func MakeIRODSErrorFromString(code ErrorCode, message string) error { - return fmt.Errorf("iRODS Error - %d (%s): %s", int(code), GetIRODSErrorString(code), message) -} diff --git a/irods/fs/collection.go b/irods/fs/collection.go index 5fbb544..10500d9 100644 --- a/irods/fs/collection.go +++ b/irods/fs/collection.go @@ -60,6 +60,11 @@ func GetCollection(conn *connection.IRODSConnection, path string) (*types.IRODSC return nil, fmt.Errorf("Could not receive a collection query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + return nil, fmt.Errorf("Received a collection query error - %v", err) + } + if queryResult.RowCount != 1 { // file not found return nil, types.NewFileNotFoundErrorf("Could not find a collection") @@ -150,6 +155,16 @@ func ListCollectionMeta(conn *connection.IRODSConnection, path string) ([]*types return nil, fmt.Errorf("Could not receive a collection metadata query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return metas, nil + } + + return nil, fmt.Errorf("Received a collection metadata query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -235,6 +250,16 @@ func ListCollectionAccess(conn *connection.IRODSConnection, path string) ([]*typ return nil, fmt.Errorf("Could not receive a collection access query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return accesses, nil + } + + return nil, fmt.Errorf("Received a collection access query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -318,6 +343,16 @@ func ListSubCollections(conn *connection.IRODSConnection, path string) ([]*types return nil, fmt.Errorf("Could not receive a collection query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return collections, nil + } + + return nil, fmt.Errorf("Received a collection query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -508,6 +543,16 @@ func SearchCollectionsByMeta(conn *connection.IRODSConnection, metaName string, return nil, fmt.Errorf("Could not receive a collection query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return collections, nil + } + + return nil, fmt.Errorf("Received a collection query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -610,6 +655,16 @@ func SearchCollectionsByMetaWildcard(conn *connection.IRODSConnection, metaName return nil, fmt.Errorf("Could not receive a collection query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return collections, nil + } + + return nil, fmt.Errorf("Received a collection query error - %v", err) + } + if queryResult.RowCount == 0 { break } diff --git a/irods/fs/data_object.go b/irods/fs/data_object.go index bf3c884..3442c2e 100644 --- a/irods/fs/data_object.go +++ b/irods/fs/data_object.go @@ -86,6 +86,11 @@ func GetDataObject(conn *connection.IRODSConnection, collection *types.IRODSColl return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + return nil, fmt.Errorf("Received a data object query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -254,6 +259,11 @@ func GetDataObjectMasterReplica(conn *connection.IRODSConnection, collection *ty return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + return nil, fmt.Errorf("Received a data object query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -400,6 +410,16 @@ func ListDataObjects(conn *connection.IRODSConnection, collection *types.IRODSCo return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return dataObjects, nil + } + + return nil, fmt.Errorf("Received a data object query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -563,6 +583,16 @@ func ListDataObjectsMasterReplica(conn *connection.IRODSConnection, collection * return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return dataObjects, nil + } + + return nil, fmt.Errorf("Received a data object query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -697,6 +727,16 @@ func ListDataObjectMeta(conn *connection.IRODSConnection, collection *types.IROD return nil, fmt.Errorf("Could not receive a data object metadata query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return metas, nil + } + + return nil, fmt.Errorf("Received a data object metadata query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -784,6 +824,16 @@ func ListDataObjectAccess(conn *connection.IRODSConnection, collection *types.IR return nil, fmt.Errorf("Could not receive a data object access query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return accesses, nil + } + + return nil, fmt.Errorf("Received a data object access query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -1128,6 +1178,16 @@ func SearchDataObjectsByMeta(conn *connection.IRODSConnection, metaName string, return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return dataObjects, nil + } + + return nil, fmt.Errorf("Received a data object query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -1311,6 +1371,16 @@ func SearchDataObjectsMasterReplicaByMeta(conn *connection.IRODSConnection, meta return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return dataObjects, nil + } + + return nil, fmt.Errorf("Received a data object query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -1475,6 +1545,16 @@ func SearchDataObjectsByMetaWildcard(conn *connection.IRODSConnection, metaName return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return dataObjects, nil + } + + return nil, fmt.Errorf("Received a data object query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -1659,6 +1739,16 @@ func SearchDataObjectsMasterReplicaByMetaWildcard(conn *connection.IRODSConnecti return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return dataObjects, nil + } + + return nil, fmt.Errorf("Received a data object query error - %v", err) + } + if queryResult.RowCount == 0 { break } diff --git a/irods/fs/resource.go b/irods/fs/resource.go index 88f4cbb..0d829e3 100644 --- a/irods/fs/resource.go +++ b/irods/fs/resource.go @@ -12,7 +12,7 @@ import ( "github.com/cyverse/go-irodsclient/irods/util" ) -// GetResource returns a data object for the path +// GetResource returns a resource for the name func GetResource(conn *connection.IRODSConnection, name string) (*types.IRODSResource, error) { if conn == nil || !conn.IsConnected() { return nil, fmt.Errorf("connection is nil or disconnected") @@ -37,7 +37,12 @@ func GetResource(conn *connection.IRODSConnection, name string) (*types.IRODSRes queryResult := message.IRODSMessageQueryResult{} err := conn.Request(query, &queryResult) if err != nil { - return nil, fmt.Errorf("Could not receive a data object query result message - %v", err) + return nil, fmt.Errorf("Could not receive a resource query result message - %v", err) + } + + err = queryResult.CheckError() + if err != nil { + return nil, fmt.Errorf("Received a data resource query error - %v", err) } if queryResult.ContinueIndex != 0 { @@ -49,7 +54,7 @@ func GetResource(conn *connection.IRODSConnection, name string) (*types.IRODSRes } if queryResult.AttributeCount > len(queryResult.SQLResult) { - return nil, fmt.Errorf("Could not receive data object attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) + return nil, fmt.Errorf("Could not receive resource attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) } resource := &types.IRODSResource{} @@ -57,7 +62,7 @@ func GetResource(conn *connection.IRODSConnection, name string) (*types.IRODSRes for attr := 0; attr < queryResult.AttributeCount; attr++ { sqlResult := queryResult.SQLResult[attr] if len(sqlResult.Values) != queryResult.RowCount { - return nil, fmt.Errorf("Could not receive data object rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) + return nil, fmt.Errorf("Could not receive resource rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) } value := sqlResult.Values[0] diff --git a/irods/fs/usergroup.go b/irods/fs/usergroup.go index 7a404f0..6576a9b 100644 --- a/irods/fs/usergroup.go +++ b/irods/fs/usergroup.go @@ -38,6 +38,11 @@ func GetGroup(conn *connection.IRODSConnection, group string) (*types.IRODSUser, return nil, fmt.Errorf("Could not receive a group query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + return nil, fmt.Errorf("Received a group query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -127,6 +132,16 @@ func ListGroupUsers(conn *connection.IRODSConnection, group string) ([]*types.IR return nil, fmt.Errorf("Could not receive a group user query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return users, nil + } + + return nil, fmt.Errorf("Received a group user query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -212,6 +227,16 @@ func ListGroups(conn *connection.IRODSConnection) ([]*types.IRODSUser, error) { return nil, fmt.Errorf("Could not receive a group query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return groups, nil + } + + return nil, fmt.Errorf("Received a group query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -296,6 +321,16 @@ func ListUsers(conn *connection.IRODSConnection) ([]*types.IRODSUser, error) { return nil, fmt.Errorf("Could not receive a user query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return users, nil + } + + return nil, fmt.Errorf("Received a user query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -378,6 +413,16 @@ func ListUserGroupNames(conn *connection.IRODSConnection, user string) ([]string return nil, fmt.Errorf("Could not receive a group query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return groups, nil + } + + return nil, fmt.Errorf("Received a group query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -439,6 +484,16 @@ func ListUserResourceQuota(conn *connection.IRODSConnection, user string) ([]*ty return nil, fmt.Errorf("Could not receive a quota query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return quota, nil + } + + return nil, fmt.Errorf("Received a quota query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -492,8 +547,8 @@ func ListUserResourceQuota(conn *connection.IRODSConnection, user string) ([]*ty return quota, nil } -// ListUserGlobalQuota lists the global quota of a user or group -func ListUserGlobalQuota(conn *connection.IRODSConnection, user string) (*types.IRODSQuota, error) { +// GetUserGlobalQuota returns the global quota of a user or group +func GetUserGlobalQuota(conn *connection.IRODSConnection, user string) (*types.IRODSQuota, error) { if conn == nil || !conn.IsConnected() { return nil, fmt.Errorf("connection is nil or disconnected") } @@ -517,6 +572,11 @@ func ListUserGlobalQuota(conn *connection.IRODSConnection, user string) (*types. return nil, fmt.Errorf("Could not receive a quota query result message - %v", err) } + err = queryResult.CheckError() + if err != nil { + return nil, fmt.Errorf("Received a quota query error - %v", err) + } + if queryResult.RowCount == 0 { break } @@ -600,7 +660,7 @@ func DeleteUserMeta(conn *connection.IRODSConnection, user string, metadata *typ return conn.RequestAndCheck(request, &response) } -// ListUserMeta returns a data object metadata for the path +// ListUserMeta returns a user metadata for the path func ListUserMeta(conn *connection.IRODSConnection, user string) ([]*types.IRODSMeta, error) { if conn == nil || !conn.IsConnected() { return nil, fmt.Errorf("connection is nil or disconnected") @@ -623,7 +683,17 @@ func ListUserMeta(conn *connection.IRODSConnection, user string) ([]*types.IRODS queryResult := message.IRODSMessageQueryResult{} err := conn.Request(query, &queryResult) if err != nil { - return nil, fmt.Errorf("Could not receive a user object metadata query result message - %v", err) + return nil, fmt.Errorf("Could not receive a user metadata query result message - %v", err) + } + + err = queryResult.CheckError() + if err != nil { + if types.GetIRODSErrorCode(err) == common.CAT_NO_ROWS_FOUND { + // empty + return metas, nil + } + + return nil, fmt.Errorf("Received a user metadata query error - %v", err) } if queryResult.RowCount == 0 { @@ -631,7 +701,7 @@ func ListUserMeta(conn *connection.IRODSConnection, user string) ([]*types.IRODS } if queryResult.AttributeCount > len(queryResult.SQLResult) { - return nil, fmt.Errorf("Could not receive user object metadata attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) + return nil, fmt.Errorf("Could not receive user metadata attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult)) } pagenatedMetas := make([]*types.IRODSMeta, queryResult.RowCount, queryResult.RowCount) @@ -639,7 +709,7 @@ func ListUserMeta(conn *connection.IRODSConnection, user string) ([]*types.IRODS for attr := 0; attr < queryResult.AttributeCount; attr++ { sqlResult := queryResult.SQLResult[attr] if len(sqlResult.Values) != queryResult.RowCount { - return nil, fmt.Errorf("Could not receive user object metadata rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) + return nil, fmt.Errorf("Could not receive user metadata rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values)) } for row := 0; row < queryResult.RowCount; row++ { @@ -659,7 +729,7 @@ func ListUserMeta(conn *connection.IRODSConnection, user string) ([]*types.IRODS case int(common.ICAT_COLUMN_META_USER_ATTR_ID): avuID, err := strconv.ParseInt(value, 10, 64) if err != nil { - return nil, fmt.Errorf("Could not parse user object metadata id - %s", value) + return nil, fmt.Errorf("Could not parse user metadata id - %s", value) } pagenatedMetas[row].AVUID = avuID case int(common.ICAT_COLUMN_META_USER_ATTR_NAME): diff --git a/irods/message/admin_response.go b/irods/message/admin_response.go index 4e3c9ad..acd72c0 100644 --- a/irods/message/admin_response.go +++ b/irods/message/admin_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageAdminResponse stores alter metadata response @@ -15,7 +16,7 @@ type IRODSMessageAdminResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageAdminResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/auth_result.go b/irods/message/auth_result.go index e47fdfa..d291ccc 100644 --- a/irods/message/auth_result.go +++ b/irods/message/auth_result.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageAuthResult stores authentication result @@ -15,7 +16,7 @@ type IRODSMessageAuthResult struct { // CheckError returns error if server returned an error func (msg *IRODSMessageAuthResult) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/closeobj_response.go b/irods/message/closeobj_response.go index 307be8f..daf125b 100644 --- a/irods/message/closeobj_response.go +++ b/irods/message/closeobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageCloseobjResponse stores data object close response @@ -15,7 +16,7 @@ type IRODSMessageCloseobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageCloseobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/cpobj_response.go b/irods/message/cpobj_response.go index aee0a33..5614adf 100644 --- a/irods/message/cpobj_response.go +++ b/irods/message/cpobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageCpobjResponse stores data object copy response @@ -15,7 +16,7 @@ type IRODSMessageCpobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageCpobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/createobj_response.go b/irods/message/createobj_response.go index 9c6786f..dabd963 100644 --- a/irods/message/createobj_response.go +++ b/irods/message/createobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageCreateobjResponse stores data object creation response @@ -15,7 +16,7 @@ type IRODSMessageCreateobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageCreateobjResponse) CheckError() error { if msg.FileDescriptor < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.FileDescriptor)) + return types.NewIRODSError(common.ErrorCode(msg.FileDescriptor)) } return nil } diff --git a/irods/message/cs_negotiation.go b/irods/message/cs_negotiation.go index 69a8ed7..de99a7c 100644 --- a/irods/message/cs_negotiation.go +++ b/irods/message/cs_negotiation.go @@ -48,7 +48,7 @@ func (msg *IRODSMessageCSNegotiation) FromBytes(bytes []byte) error { // CheckError returns error if server returned an error func (msg *IRODSMessageCSNegotiation) CheckError() error { if msg.Status < 0 { - return common.MakeIRODSErrorFromString(common.ErrorCode(msg.Status), msg.Result) + return types.NewIRODSErrorWithString(common.ErrorCode(msg.Status), msg.Result) } return nil } diff --git a/irods/message/endtransaction_response.go b/irods/message/endtransaction_response.go index 32185cf..0514a31 100644 --- a/irods/message/endtransaction_response.go +++ b/irods/message/endtransaction_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageEndTransactionResponse stores end transaction response @@ -15,7 +16,7 @@ type IRODSMessageEndTransactionResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageEndTransactionResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/filestat_response.go b/irods/message/filestat_response.go index c5b3bc9..3a352eb 100644 --- a/irods/message/filestat_response.go +++ b/irods/message/filestat_response.go @@ -3,6 +3,9 @@ package message import ( "encoding/xml" "fmt" + + "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageFileStatResponse stores data object read response @@ -21,6 +24,9 @@ type IRODSMessageFileStatResponse struct { ChangeTime int `xml:"st_ctim"` BlkSize int `xml:"st_blksize"` Blocks int `xml:"st_blocks"` + + // stores error return + Result int `xml:"-"` } // GetBytes returns byte array @@ -29,6 +35,14 @@ func (msg *IRODSMessageFileStatResponse) GetBytes() ([]byte, error) { return xmlBytes, err } +// CheckError returns error if server returned an error +func (msg *IRODSMessageFileStatResponse) CheckError() error { + if msg.Result < 0 { + return types.NewIRODSError(common.ErrorCode(msg.Result)) + } + return nil +} + // FromBytes returns struct from bytes func (msg *IRODSMessageFileStatResponse) FromBytes(bytes []byte) error { err := xml.Unmarshal(bytes, msg) @@ -42,5 +56,6 @@ func (msg *IRODSMessageFileStatResponse) FromMessage(msgIn *IRODSMessage) error } err := msg.FromBytes(msgIn.Body.Message) + msg.Result = int(msgIn.Body.IntInfo) return err } diff --git a/irods/message/mkcol_response.go b/irods/message/mkcol_response.go index 6d83a1b..11b308d 100644 --- a/irods/message/mkcol_response.go +++ b/irods/message/mkcol_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageMkcolResponse stores collection creation response @@ -15,7 +16,7 @@ type IRODSMessageMkcolResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageMkcolResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/modaccess_response.go b/irods/message/modaccess_response.go index c985217..b13aca7 100644 --- a/irods/message/modaccess_response.go +++ b/irods/message/modaccess_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageModAccessResponse stores alter metadata response @@ -15,7 +16,7 @@ type IRODSMessageModAccessResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageModAccessResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/modcol_response.go b/irods/message/modcol_response.go index c3a977f..4e932b2 100644 --- a/irods/message/modcol_response.go +++ b/irods/message/modcol_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageModColResponse stores alter metadata response @@ -15,7 +16,7 @@ type IRODSMessageModColResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageModColResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/modmeta_response.go b/irods/message/modmeta_response.go index 23b55ff..ae0eb1f 100644 --- a/irods/message/modmeta_response.go +++ b/irods/message/modmeta_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageModMetaResponse stores alter metadata response @@ -15,7 +16,7 @@ type IRODSMessageModMetaResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageModMetaResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/mvcol_response.go b/irods/message/mvcol_response.go index 2c61f86..6ff7f4b 100644 --- a/irods/message/mvcol_response.go +++ b/irods/message/mvcol_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageMvcolResponse stores collection move response @@ -15,7 +16,7 @@ type IRODSMessageMvcolResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageMvcolResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/mvobj_response.go b/irods/message/mvobj_response.go index b7af613..39b47d9 100644 --- a/irods/message/mvobj_response.go +++ b/irods/message/mvobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageMvobjResponse stores data object move response @@ -15,7 +16,7 @@ type IRODSMessageMvobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageMvobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/openobj_response.go b/irods/message/openobj_response.go index e4bef42..135df47 100644 --- a/irods/message/openobj_response.go +++ b/irods/message/openobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageOpenobjResponse stores data object open response @@ -15,7 +16,7 @@ type IRODSMessageOpenobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageOpenobjResponse) CheckError() error { if msg.FileDescriptor < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.FileDescriptor)) + return types.NewIRODSError(common.ErrorCode(msg.FileDescriptor)) } return nil } diff --git a/irods/message/query_result.go b/irods/message/query_result.go index 803553b..3d13c0e 100644 --- a/irods/message/query_result.go +++ b/irods/message/query_result.go @@ -3,6 +3,9 @@ package message import ( "encoding/xml" "fmt" + + "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageQueryResult stores query result @@ -13,6 +16,9 @@ type IRODSMessageQueryResult struct { ContinueIndex int `xml:"continueInx"` TotalRowCount int `xml:"totalRowCount"` SQLResult []IRODSMessageSQLResult `xml:"SqlResult_PI"` + + // stores error result + Result int `xml:"-"` } // GetBytes returns byte array @@ -21,6 +27,14 @@ func (msg *IRODSMessageQueryResult) GetBytes() ([]byte, error) { return xmlBytes, err } +// CheckError returns error if server returned an error +func (msg *IRODSMessageQueryResult) CheckError() error { + if msg.Result < 0 { + return types.NewIRODSError(common.ErrorCode(msg.Result)) + } + return nil +} + // FromBytes returns struct from bytes func (msg *IRODSMessageQueryResult) FromBytes(bytes []byte) error { err := xml.Unmarshal(bytes, msg) @@ -34,5 +48,6 @@ func (msg *IRODSMessageQueryResult) FromMessage(msgIn *IRODSMessage) error { } err := msg.FromBytes(msgIn.Body.Message) + msg.Result = int(msgIn.Body.IntInfo) return err } diff --git a/irods/message/readobj_response.go b/irods/message/readobj_response.go index be77a1c..383a1cc 100644 --- a/irods/message/readobj_response.go +++ b/irods/message/readobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageReadobjResponse stores data object read response @@ -16,7 +17,7 @@ type IRODSMessageReadobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageReadobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/replobj_response.go b/irods/message/replobj_response.go index 429d4c8..68be10d 100644 --- a/irods/message/replobj_response.go +++ b/irods/message/replobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageReplobjResponse stores data object replication response @@ -15,7 +16,7 @@ type IRODSMessageReplobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageReplobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/rmcol_response.go b/irods/message/rmcol_response.go index 9149488..de0d2b8 100644 --- a/irods/message/rmcol_response.go +++ b/irods/message/rmcol_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageRmcolResponse stores collection deletion response @@ -15,7 +16,7 @@ type IRODSMessageRmcolResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageRmcolResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/rmobj_response.go b/irods/message/rmobj_response.go index 76574c9..bda1d01 100644 --- a/irods/message/rmobj_response.go +++ b/irods/message/rmobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageRmobjResponse stores data object deletion response @@ -15,7 +16,7 @@ type IRODSMessageRmobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageRmobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/seekobj_response.go b/irods/message/seekobj_response.go index 9961b66..d72f9aa 100644 --- a/irods/message/seekobj_response.go +++ b/irods/message/seekobj_response.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageSeekobjResponse stores data object seek response @@ -22,7 +23,7 @@ func (msg *IRODSMessageSeekobjResponse) FromBytes(bytes []byte) error { // CheckError returns error if server returned an error func (msg *IRODSMessageSeekobjResponse) CheckError() error { if msg.Offset < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Offset)) + return types.NewIRODSError(common.ErrorCode(msg.Offset)) } return nil } diff --git a/irods/message/ticketadmin_response.go b/irods/message/ticketadmin_response.go index d7bcf7f..8a739f9 100644 --- a/irods/message/ticketadmin_response.go +++ b/irods/message/ticketadmin_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageTicketAdminResponse stores ticket admin response @@ -15,7 +16,7 @@ type IRODSMessageTicketAdminResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageTicketAdminResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/trimobj_response.go b/irods/message/trimobj_response.go index 4672c99..36b6ea0 100644 --- a/irods/message/trimobj_response.go +++ b/irods/message/trimobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageTrimobjResponse stores data object trim response @@ -15,7 +16,7 @@ type IRODSMessageTrimobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageTrimobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/truncobj_response.go b/irods/message/truncobj_response.go index de1ea85..a7e7484 100644 --- a/irods/message/truncobj_response.go +++ b/irods/message/truncobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageTruncobjResponse stores data object truncation response @@ -15,7 +16,7 @@ type IRODSMessageTruncobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageTruncobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/useradmin_response.go b/irods/message/useradmin_response.go index 5b79926..8eba2f1 100644 --- a/irods/message/useradmin_response.go +++ b/irods/message/useradmin_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageUserAdminResponse stores alter metadata response @@ -15,7 +16,7 @@ type IRODSMessageUserAdminResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageUserAdminResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/message/version.go b/irods/message/version.go index 6f1cb11..4759849 100644 --- a/irods/message/version.go +++ b/irods/message/version.go @@ -38,7 +38,7 @@ func (msg *IRODSMessageVersion) FromBytes(bytes []byte) error { // CheckError returns error if server returned an error func (msg *IRODSMessageVersion) CheckError() error { if msg.Status < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Status)) + return types.NewIRODSError(common.ErrorCode(msg.Status)) } return nil } diff --git a/irods/message/writeobj_response.go b/irods/message/writeobj_response.go index 8a203d4..0cf96f4 100644 --- a/irods/message/writeobj_response.go +++ b/irods/message/writeobj_response.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cyverse/go-irodsclient/irods/common" + "github.com/cyverse/go-irodsclient/irods/types" ) // IRODSMessageWriteobjResponse stores data object write response @@ -15,7 +16,7 @@ type IRODSMessageWriteobjResponse struct { // CheckError returns error if server returned an error func (msg *IRODSMessageWriteobjResponse) CheckError() error { if msg.Result < 0 { - return common.MakeIRODSError(common.ErrorCode(msg.Result)) + return types.NewIRODSError(common.ErrorCode(msg.Result)) } return nil } diff --git a/irods/types/account.go b/irods/types/account.go index 06158b6..f990b91 100644 --- a/irods/types/account.go +++ b/irods/types/account.go @@ -302,6 +302,6 @@ func (account *IRODSAccount) UseTicket() bool { func (account *IRODSAccount) MaskSensitiveData() *IRODSAccount { maskedAccount := *account maskedAccount.Password = "" - + maskedAccount.Ticket = "" return &maskedAccount } diff --git a/irods/types/error.go b/irods/types/error.go new file mode 100644 index 0000000..e8cd480 --- /dev/null +++ b/irods/types/error.go @@ -0,0 +1,64 @@ +package types + +import ( + "errors" + "fmt" + + "github.com/cyverse/go-irodsclient/irods/common" +) + +// IRODSError contains irods error information +type IRODSError struct { + Code common.ErrorCode + Message string + ContextualMessage string +} + +// NewIRODSError creates a new IRODSError +func NewIRODSError(code common.ErrorCode) *IRODSError { + return &IRODSError{ + Code: code, + Message: common.GetIRODSErrorString(code), + ContextualMessage: "", + } +} + +func NewIRODSErrorWithString(code common.ErrorCode, message string) *IRODSError { + return &IRODSError{ + Code: code, + Message: common.GetIRODSErrorString(code), + ContextualMessage: message, + } +} + +// Error returns error message +func (err *IRODSError) Error() string { + if len(err.ContextualMessage) > 0 { + return fmt.Sprintf("%s - %s", err.Message, err.ContextualMessage) + } + return err.Message +} + +// Code returns error code +func (err *IRODSError) GetCode() common.ErrorCode { + return err.Code +} + +// ToString stringifies the object +func (err *IRODSError) ToString() string { + return fmt.Sprintf("", err.Code, err.Message, err.ContextualMessage) +} + +// IsIRODSError checks if the given error is IRODSError +func IsIRODSError(err error) bool { + return errors.Is(err, &IRODSError{}) +} + +// IsIRODSError checks if the given error is IRODSError +func GetIRODSErrorCode(err error) common.ErrorCode { + var irodsError *IRODSError + if errors.As(err, &irodsError) { + return irodsError.GetCode() + } + return common.ErrorCode(0) +} From fb9c8887384aa0e4eed36eb0185b2a7aeb3f9682 Mon Sep 17 00:00:00 2001 From: Illyoung Choi Date: Wed, 11 Aug 2021 17:17:23 -0700 Subject: [PATCH 4/4] Use collection name instead of id to find data object in the collection --- examples/ticket_list_dir/account.yml | 9 ++++ examples/ticket_list_dir/list_dir.go | 72 ++++++++++++++++++++++++++++ irods/fs/data_object.go | 25 +++++----- 3 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 examples/ticket_list_dir/account.yml create mode 100644 examples/ticket_list_dir/list_dir.go diff --git a/examples/ticket_list_dir/account.yml b/examples/ticket_list_dir/account.yml new file mode 100644 index 0000000..1922395 --- /dev/null +++ b/examples/ticket_list_dir/account.yml @@ -0,0 +1,9 @@ +host: + hostname: "data.cyverse.org" + port: 1247 +user: + username: "" + password: "" + zone: "iplant" + ticket: "" +auth_scheme: "native" \ No newline at end of file diff --git a/examples/ticket_list_dir/list_dir.go b/examples/ticket_list_dir/list_dir.go new file mode 100644 index 0000000..706455d --- /dev/null +++ b/examples/ticket_list_dir/list_dir.go @@ -0,0 +1,72 @@ +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + + "github.com/cyverse/go-irodsclient/fs" + "github.com/cyverse/go-irodsclient/irods/types" + "github.com/cyverse/go-irodsclient/irods/util" +) + +func main() { + util.SetLogLevel(9) + + // Parse cli parameters + flag.Parse() + args := flag.Args() + + if len(args) != 1 { + fmt.Fprintf(os.Stderr, "Give an iRODS path!\n") + os.Exit(1) + } + + inputPath := args[0] + + // Read account configuration from YAML file + yaml, err := ioutil.ReadFile("account.yml") + if err != nil { + util.LogErrorf("err - %v", err) + panic(err) + } + + account, err := types.CreateIRODSAccountFromYAML(yaml) + if err != nil { + util.LogErrorf("err - %v", err) + panic(err) + } + + util.LogDebugf("Account : %v", account.MaskSensitiveData()) + + // Create a file system + appName := "list_dir_ticket" + filesystem, err := fs.NewFileSystemWithDefault(account, appName) + if err != nil { + util.LogErrorf("err - %v", err) + panic(err) + } + + defer filesystem.Release() + + entries, err := filesystem.List(inputPath) + if err != nil { + util.LogErrorf("err - %v", err) + panic(err) + } + + if len(entries) == 0 { + fmt.Printf("Found no entries in the directory - %s\n", inputPath) + } else { + fmt.Printf("DIR: %s\n", inputPath) + for _, entry := range entries { + if entry.Type == fs.FSFileEntry { + fmt.Printf("> FILE:\t%s\t%d\n", entry.Path, entry.Size) + } else { + // dir + fmt.Printf("> DIRECTORY:\t%s\n", entry.Path) + } + } + } +} diff --git a/irods/fs/data_object.go b/irods/fs/data_object.go index 3442c2e..04b6842 100644 --- a/irods/fs/data_object.go +++ b/irods/fs/data_object.go @@ -75,8 +75,9 @@ func GetDataObject(conn *connection.IRODSConnection, collection *types.IRODSColl query.AddSelect(common.ICAT_COLUMN_D_CREATE_TIME, 1) query.AddSelect(common.ICAT_COLUMN_D_MODIFY_TIME, 1) - collidCondVal := fmt.Sprintf("= '%d'", collection.ID) - query.AddCondition(common.ICAT_COLUMN_D_COLL_ID, collidCondVal) + collCondVal := fmt.Sprintf("= '%s'", collection.Path) + query.AddCondition(common.ICAT_COLUMN_COLL_NAME, collCondVal) + pathCondVal := fmt.Sprintf("= '%s'", filename) query.AddCondition(common.ICAT_COLUMN_DATA_NAME, pathCondVal) @@ -247,8 +248,8 @@ func GetDataObjectMasterReplica(conn *connection.IRODSConnection, collection *ty query.AddSelect(common.ICAT_COLUMN_D_CREATE_TIME, 1) query.AddSelect(common.ICAT_COLUMN_D_MODIFY_TIME, 1) - collidCondVal := fmt.Sprintf("= '%d'", collection.ID) - query.AddCondition(common.ICAT_COLUMN_D_COLL_ID, collidCondVal) + collCondVal := fmt.Sprintf("= '%s'", collection.Path) + query.AddCondition(common.ICAT_COLUMN_COLL_NAME, collCondVal) pathCondVal := fmt.Sprintf("= '%s'", filename) query.AddCondition(common.ICAT_COLUMN_DATA_NAME, pathCondVal) query.AddCondition(common.ICAT_COLUMN_DATA_REPL_NUM, "= '0'") @@ -401,8 +402,8 @@ func ListDataObjects(conn *connection.IRODSConnection, collection *types.IRODSCo query.AddSelect(common.ICAT_COLUMN_D_CREATE_TIME, 1) query.AddSelect(common.ICAT_COLUMN_D_MODIFY_TIME, 1) - collidCondVal := fmt.Sprintf("= '%d'", collection.ID) - query.AddCondition(common.ICAT_COLUMN_D_COLL_ID, collidCondVal) + collCondVal := fmt.Sprintf("= '%s'", collection.Path) + query.AddCondition(common.ICAT_COLUMN_COLL_NAME, collCondVal) queryResult := message.IRODSMessageQueryResult{} err := conn.Request(query, &queryResult) @@ -573,8 +574,8 @@ func ListDataObjectsMasterReplica(conn *connection.IRODSConnection, collection * query.AddSelect(common.ICAT_COLUMN_D_CREATE_TIME, 1) query.AddSelect(common.ICAT_COLUMN_D_MODIFY_TIME, 1) - collidCondVal := fmt.Sprintf("= '%d'", collection.ID) - query.AddCondition(common.ICAT_COLUMN_D_COLL_ID, collidCondVal) + collCondVal := fmt.Sprintf("= '%s'", collection.Path) + query.AddCondition(common.ICAT_COLUMN_COLL_NAME, collCondVal) query.AddCondition(common.ICAT_COLUMN_DATA_REPL_NUM, "= '0'") queryResult := message.IRODSMessageQueryResult{} @@ -716,8 +717,8 @@ func ListDataObjectMeta(conn *connection.IRODSConnection, collection *types.IROD query.AddSelect(common.ICAT_COLUMN_META_DATA_ATTR_VALUE, 1) query.AddSelect(common.ICAT_COLUMN_META_DATA_ATTR_UNITS, 1) - collidCondVal := fmt.Sprintf("= '%d'", collection.ID) - query.AddCondition(common.ICAT_COLUMN_D_COLL_ID, collidCondVal) + collCondVal := fmt.Sprintf("= '%s'", collection.Path) + query.AddCondition(common.ICAT_COLUMN_COLL_NAME, collCondVal) nameCondVal := fmt.Sprintf("= '%s'", filename) query.AddCondition(common.ICAT_COLUMN_DATA_NAME, nameCondVal) @@ -813,8 +814,8 @@ func ListDataObjectAccess(conn *connection.IRODSConnection, collection *types.IR query.AddSelect(common.ICAT_COLUMN_USER_ZONE, 1) query.AddSelect(common.ICAT_COLUMN_USER_TYPE, 1) - collidCondVal := fmt.Sprintf("= '%d'", collection.ID) - query.AddCondition(common.ICAT_COLUMN_D_COLL_ID, collidCondVal) + collCondVal := fmt.Sprintf("= '%s'", collection.Path) + query.AddCondition(common.ICAT_COLUMN_COLL_NAME, collCondVal) nameCondVal := fmt.Sprintf("= '%s'", filename) query.AddCondition(common.ICAT_COLUMN_DATA_NAME, nameCondVal)