github.com/gophercloud/gophercloud@v1.11.0/openstack/sharedfilesystems/v2/sharetransfers/results.go (about) 1 package sharetransfers 2 3 import ( 4 "encoding/json" 5 "net/url" 6 "strconv" 7 "time" 8 9 "github.com/gophercloud/gophercloud" 10 "github.com/gophercloud/gophercloud/pagination" 11 ) 12 13 const ( 14 invalidMarker = "-1" 15 ) 16 17 // Transfer represents a Share Transfer record. 18 type Transfer struct { 19 ID string `json:"id"` 20 Accepted bool `json:"accepted"` 21 AuthKey string `json:"auth_key"` 22 Name string `json:"name"` 23 SourceProjectID string `json:"source_project_id"` 24 DestinationProjectID string `json:"destination_project_id"` 25 ResourceID string `json:"resource_id"` 26 ResourceType string `json:"resource_type"` 27 CreatedAt time.Time `json:"-"` 28 ExpiresAt time.Time `json:"-"` 29 Links []map[string]string `json:"links"` 30 } 31 32 // UnmarshalJSON is our unmarshalling helper. 33 func (r *Transfer) UnmarshalJSON(b []byte) error { 34 type tmp Transfer 35 var s struct { 36 tmp 37 CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"` 38 ExpiresAt gophercloud.JSONRFC3339MilliNoZ `json:"expires_at"` 39 } 40 err := json.Unmarshal(b, &s) 41 if err != nil { 42 return err 43 } 44 *r = Transfer(s.tmp) 45 46 r.CreatedAt = time.Time(s.CreatedAt) 47 r.ExpiresAt = time.Time(s.ExpiresAt) 48 49 return err 50 } 51 52 type commonResult struct { 53 gophercloud.Result 54 } 55 56 // Extract will get the Transfer object out of the commonResult object. 57 func (r commonResult) Extract() (*Transfer, error) { 58 var s Transfer 59 err := r.ExtractInto(&s) 60 return &s, err 61 } 62 63 // ExtractInto converts our response data into a transfer struct. 64 func (r commonResult) ExtractInto(v interface{}) error { 65 return r.Result.ExtractIntoStructPtr(v, "transfer") 66 } 67 68 // CreateResult contains the response body and error from a Create request. 69 type CreateResult struct { 70 commonResult 71 } 72 73 // GetResult contains the response body and error from a Get request. 74 type GetResult struct { 75 commonResult 76 } 77 78 // DeleteResult contains the response body and error from a Delete request. 79 type DeleteResult struct { 80 gophercloud.ErrResult 81 } 82 83 // AcceptResult contains the response body and error from an Accept request. 84 type AcceptResult struct { 85 gophercloud.ErrResult 86 } 87 88 // ExtractTransfers extracts and returns Transfers. It is used while iterating over a transfers.List call. 89 func ExtractTransfers(r pagination.Page) ([]Transfer, error) { 90 var s []Transfer 91 err := ExtractTransfersInto(r, &s) 92 return s, err 93 } 94 95 // ExtractTransfersInto similar to ExtractInto but operates on a `list` of transfers 96 func ExtractTransfersInto(r pagination.Page, v interface{}) error { 97 return r.(TransferPage).Result.ExtractIntoSlicePtr(v, "transfers") 98 } 99 100 // TransferPage is a pagination.pager that is returned from a call to the List function. 101 type TransferPage struct { 102 pagination.MarkerPageBase 103 } 104 105 // NextPageURL generates the URL for the page of results after this one. 106 func (r TransferPage) NextPageURL() (string, error) { 107 currentURL := r.URL 108 mark, err := r.Owner.LastMarker() 109 if err != nil { 110 return "", err 111 } 112 if mark == invalidMarker { 113 return "", nil 114 } 115 116 q := currentURL.Query() 117 q.Set("offset", mark) 118 currentURL.RawQuery = q.Encode() 119 return currentURL.String(), nil 120 } 121 122 // LastMarker returns the last offset in a ListResult. 123 func (r TransferPage) LastMarker() (string, error) { 124 replicas, err := ExtractTransfers(r) 125 if err != nil { 126 return invalidMarker, err 127 } 128 if len(replicas) == 0 { 129 return invalidMarker, nil 130 } 131 132 u, err := url.Parse(r.URL.String()) 133 if err != nil { 134 return invalidMarker, err 135 } 136 queryParams := u.Query() 137 offset := queryParams.Get("offset") 138 limit := queryParams.Get("limit") 139 140 // Limit is not present, only one page required 141 if limit == "" { 142 return invalidMarker, nil 143 } 144 145 iOffset := 0 146 if offset != "" { 147 iOffset, err = strconv.Atoi(offset) 148 if err != nil { 149 return invalidMarker, err 150 } 151 } 152 iLimit, err := strconv.Atoi(limit) 153 if err != nil { 154 return invalidMarker, err 155 } 156 iOffset = iOffset + iLimit 157 offset = strconv.Itoa(iOffset) 158 159 return offset, nil 160 } 161 162 // IsEmpty satisifies the IsEmpty method of the Page interface. 163 func (r TransferPage) IsEmpty() (bool, error) { 164 if r.StatusCode == 204 { 165 return true, nil 166 } 167 168 replicas, err := ExtractTransfers(r) 169 return len(replicas) == 0, err 170 }