github.com/gophercloud/gophercloud@v1.11.0/openstack/objectstorage/v1/containers/results.go (about)

     1  package containers
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/gophercloud/gophercloud"
    11  	"github.com/gophercloud/gophercloud/pagination"
    12  )
    13  
    14  // Container represents a container resource.
    15  type Container struct {
    16  	// The total number of bytes stored in the container.
    17  	Bytes int64 `json:"bytes"`
    18  
    19  	// The total number of objects stored in the container.
    20  	Count int64 `json:"count"`
    21  
    22  	// The name of the container.
    23  	Name string `json:"name"`
    24  }
    25  
    26  // ContainerPage is the page returned by a pager when traversing over a
    27  // collection of containers.
    28  type ContainerPage struct {
    29  	pagination.MarkerPageBase
    30  }
    31  
    32  // IsEmpty returns true if a ListResult contains no container names.
    33  func (r ContainerPage) IsEmpty() (bool, error) {
    34  	if r.StatusCode == 204 {
    35  		return true, nil
    36  	}
    37  
    38  	names, err := ExtractNames(r)
    39  	return len(names) == 0, err
    40  }
    41  
    42  // LastMarker returns the last container name in a ListResult.
    43  func (r ContainerPage) LastMarker() (string, error) {
    44  	names, err := ExtractNames(r)
    45  	if err != nil {
    46  		return "", err
    47  	}
    48  	if len(names) == 0 {
    49  		return "", nil
    50  	}
    51  	return names[len(names)-1], nil
    52  }
    53  
    54  // ExtractInfo is a function that takes a ListResult and returns the
    55  // containers' information.
    56  func ExtractInfo(r pagination.Page) ([]Container, error) {
    57  	var s []Container
    58  	err := (r.(ContainerPage)).ExtractInto(&s)
    59  	return s, err
    60  }
    61  
    62  // ExtractNames is a function that takes a ListResult and returns the
    63  // containers' names.
    64  func ExtractNames(page pagination.Page) ([]string, error) {
    65  	casted := page.(ContainerPage)
    66  	ct := casted.Header.Get("Content-Type")
    67  
    68  	switch {
    69  	case strings.HasPrefix(ct, "application/json"):
    70  		parsed, err := ExtractInfo(page)
    71  		if err != nil {
    72  			return nil, err
    73  		}
    74  
    75  		names := make([]string, 0, len(parsed))
    76  		for _, container := range parsed {
    77  			names = append(names, container.Name)
    78  		}
    79  		return names, nil
    80  	case strings.HasPrefix(ct, "text/plain") || ct == "":
    81  		names := make([]string, 0, 50)
    82  
    83  		body := string(page.(ContainerPage).Body.([]uint8))
    84  		for _, name := range strings.Split(body, "\n") {
    85  			if len(name) > 0 {
    86  				names = append(names, name)
    87  			}
    88  		}
    89  
    90  		return names, nil
    91  	default:
    92  		return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
    93  	}
    94  }
    95  
    96  // GetHeader represents the headers returned in the response from a Get request.
    97  type GetHeader struct {
    98  	AcceptRanges     string    `json:"Accept-Ranges"`
    99  	BytesUsed        int64     `json:"X-Container-Bytes-Used,string"`
   100  	ContentLength    int64     `json:"Content-Length,string"`
   101  	ContentType      string    `json:"Content-Type"`
   102  	Date             time.Time `json:"-"`
   103  	ObjectCount      int64     `json:"X-Container-Object-Count,string"`
   104  	Read             []string  `json:"-"`
   105  	TransID          string    `json:"X-Trans-Id"`
   106  	VersionsLocation string    `json:"X-Versions-Location"`
   107  	HistoryLocation  string    `json:"X-History-Location"`
   108  	Write            []string  `json:"-"`
   109  	StoragePolicy    string    `json:"X-Storage-Policy"`
   110  	TempURLKey       string    `json:"X-Container-Meta-Temp-URL-Key"`
   111  	TempURLKey2      string    `json:"X-Container-Meta-Temp-URL-Key-2"`
   112  	Timestamp        float64   `json:"X-Timestamp,string"`
   113  	VersionsEnabled  bool      `json:"-"`
   114  }
   115  
   116  func (r *GetHeader) UnmarshalJSON(b []byte) error {
   117  	type tmp GetHeader
   118  	var s struct {
   119  		tmp
   120  		Write           string                  `json:"X-Container-Write"`
   121  		Read            string                  `json:"X-Container-Read"`
   122  		Date            gophercloud.JSONRFC1123 `json:"Date"`
   123  		VersionsEnabled string                  `json:"X-Versions-Enabled"`
   124  	}
   125  
   126  	err := json.Unmarshal(b, &s)
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	*r = GetHeader(s.tmp)
   132  
   133  	r.Read = strings.Split(s.Read, ",")
   134  	r.Write = strings.Split(s.Write, ",")
   135  
   136  	r.Date = time.Time(s.Date)
   137  
   138  	if s.VersionsEnabled != "" {
   139  		// custom unmarshaller here is required to handle boolean value
   140  		// that starts with a capital letter
   141  		r.VersionsEnabled, err = strconv.ParseBool(s.VersionsEnabled)
   142  	}
   143  
   144  	return err
   145  }
   146  
   147  // GetResult represents the result of a get operation.
   148  type GetResult struct {
   149  	gophercloud.HeaderResult
   150  }
   151  
   152  // Extract will return a struct of headers returned from a call to Get.
   153  func (r GetResult) Extract() (*GetHeader, error) {
   154  	var s GetHeader
   155  	err := r.ExtractInto(&s)
   156  	return &s, err
   157  }
   158  
   159  // ExtractMetadata is a function that takes a GetResult (of type *http.Response)
   160  // and returns the custom metadata associated with the container.
   161  func (r GetResult) ExtractMetadata() (map[string]string, error) {
   162  	if r.Err != nil {
   163  		return nil, r.Err
   164  	}
   165  	metadata := make(map[string]string)
   166  	for k, v := range r.Header {
   167  		if strings.HasPrefix(k, "X-Container-Meta-") {
   168  			key := strings.TrimPrefix(k, "X-Container-Meta-")
   169  			metadata[key] = v[0]
   170  		}
   171  	}
   172  	return metadata, nil
   173  }
   174  
   175  // CreateHeader represents the headers returned in the response from a Create
   176  // request.
   177  type CreateHeader struct {
   178  	ContentLength int64     `json:"Content-Length,string"`
   179  	ContentType   string    `json:"Content-Type"`
   180  	Date          time.Time `json:"-"`
   181  	TransID       string    `json:"X-Trans-Id"`
   182  }
   183  
   184  func (r *CreateHeader) UnmarshalJSON(b []byte) error {
   185  	type tmp CreateHeader
   186  	var s struct {
   187  		tmp
   188  		Date gophercloud.JSONRFC1123 `json:"Date"`
   189  	}
   190  	err := json.Unmarshal(b, &s)
   191  	if err != nil {
   192  		return err
   193  	}
   194  
   195  	*r = CreateHeader(s.tmp)
   196  
   197  	r.Date = time.Time(s.Date)
   198  
   199  	return err
   200  }
   201  
   202  // CreateResult represents the result of a create operation. To extract the
   203  // the headers from the HTTP response, call its Extract method.
   204  type CreateResult struct {
   205  	gophercloud.HeaderResult
   206  }
   207  
   208  // Extract will return a struct of headers returned from a call to Create.
   209  // To extract the headers from the HTTP response, call its Extract method.
   210  func (r CreateResult) Extract() (*CreateHeader, error) {
   211  	var s CreateHeader
   212  	err := r.ExtractInto(&s)
   213  	return &s, err
   214  }
   215  
   216  // UpdateHeader represents the headers returned in the response from a Update
   217  // request.
   218  type UpdateHeader struct {
   219  	ContentLength int64     `json:"Content-Length,string"`
   220  	ContentType   string    `json:"Content-Type"`
   221  	Date          time.Time `json:"-"`
   222  	TransID       string    `json:"X-Trans-Id"`
   223  }
   224  
   225  func (r *UpdateHeader) UnmarshalJSON(b []byte) error {
   226  	type tmp UpdateHeader
   227  	var s struct {
   228  		tmp
   229  		Date gophercloud.JSONRFC1123 `json:"Date"`
   230  	}
   231  	err := json.Unmarshal(b, &s)
   232  	if err != nil {
   233  		return err
   234  	}
   235  
   236  	*r = UpdateHeader(s.tmp)
   237  
   238  	r.Date = time.Time(s.Date)
   239  
   240  	return err
   241  }
   242  
   243  // UpdateResult represents the result of an update operation. To extract the
   244  // the headers from the HTTP response, call its Extract method.
   245  type UpdateResult struct {
   246  	gophercloud.HeaderResult
   247  }
   248  
   249  // Extract will return a struct of headers returned from a call to Update.
   250  func (r UpdateResult) Extract() (*UpdateHeader, error) {
   251  	var s UpdateHeader
   252  	err := r.ExtractInto(&s)
   253  	return &s, err
   254  }
   255  
   256  // DeleteHeader represents the headers returned in the response from a Delete
   257  // request.
   258  type DeleteHeader struct {
   259  	ContentLength int64     `json:"Content-Length,string"`
   260  	ContentType   string    `json:"Content-Type"`
   261  	Date          time.Time `json:"-"`
   262  	TransID       string    `json:"X-Trans-Id"`
   263  }
   264  
   265  func (r *DeleteHeader) UnmarshalJSON(b []byte) error {
   266  	type tmp DeleteHeader
   267  	var s struct {
   268  		tmp
   269  		Date gophercloud.JSONRFC1123 `json:"Date"`
   270  	}
   271  	err := json.Unmarshal(b, &s)
   272  	if err != nil {
   273  		return err
   274  	}
   275  
   276  	*r = DeleteHeader(s.tmp)
   277  
   278  	r.Date = time.Time(s.Date)
   279  
   280  	return err
   281  }
   282  
   283  // DeleteResult represents the result of a delete operation. To extract the
   284  // headers from the HTTP response, call its Extract method.
   285  type DeleteResult struct {
   286  	gophercloud.HeaderResult
   287  }
   288  
   289  // Extract will return a struct of headers returned from a call to Delete.
   290  func (r DeleteResult) Extract() (*DeleteHeader, error) {
   291  	var s DeleteHeader
   292  	err := r.ExtractInto(&s)
   293  	return &s, err
   294  }
   295  
   296  type BulkDeleteResponse struct {
   297  	ResponseStatus string     `json:"Response Status"`
   298  	ResponseBody   string     `json:"Response Body"`
   299  	Errors         [][]string `json:"Errors"`
   300  	NumberDeleted  int        `json:"Number Deleted"`
   301  	NumberNotFound int        `json:"Number Not Found"`
   302  }
   303  
   304  // BulkDeleteResult represents the result of a bulk delete operation. To extract
   305  // the response object from the HTTP response, call its Extract method.
   306  type BulkDeleteResult struct {
   307  	gophercloud.Result
   308  }
   309  
   310  // Extract will return a BulkDeleteResponse struct returned from a BulkDelete
   311  // call.
   312  func (r BulkDeleteResult) Extract() (*BulkDeleteResponse, error) {
   313  	var s BulkDeleteResponse
   314  	err := r.ExtractInto(&s)
   315  	return &s, err
   316  }