github.com/gophercloud/gophercloud@v1.11.0/openstack/networking/v2/extensions/subnetpools/results.go (about)

     1  package subnetpools
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  	"time"
     8  
     9  	"github.com/gophercloud/gophercloud"
    10  	"github.com/gophercloud/gophercloud/pagination"
    11  )
    12  
    13  type commonResult struct {
    14  	gophercloud.Result
    15  }
    16  
    17  // Extract is a function that accepts a result and extracts a subnetpool resource.
    18  func (r commonResult) Extract() (*SubnetPool, error) {
    19  	var s struct {
    20  		SubnetPool *SubnetPool `json:"subnetpool"`
    21  	}
    22  	err := r.ExtractInto(&s)
    23  	return s.SubnetPool, err
    24  }
    25  
    26  // GetResult represents the result of a get operation. Call its Extract
    27  // method to interpret it as a SubnetPool.
    28  type GetResult struct {
    29  	commonResult
    30  }
    31  
    32  // CreateResult represents the result of a create operation. Call its Extract
    33  // method to interpret it as a SubnetPool.
    34  type CreateResult struct {
    35  	commonResult
    36  }
    37  
    38  // UpdateResult represents the result of an update operation. Call its Extract
    39  // method to interpret it as a SubnetPool.
    40  type UpdateResult struct {
    41  	commonResult
    42  }
    43  
    44  // DeleteResult represents the result of a delete operation. Call its
    45  // ExtractErr method to determine if the request succeeded or failed.
    46  type DeleteResult struct {
    47  	gophercloud.ErrResult
    48  }
    49  
    50  // SubnetPool represents a Neutron subnetpool.
    51  // A subnetpool is a pool of addresses from which subnets can be allocated.
    52  type SubnetPool struct {
    53  	// ID is the id of the subnetpool.
    54  	ID string `json:"id"`
    55  
    56  	// Name is the human-readable name of the subnetpool.
    57  	Name string `json:"name"`
    58  
    59  	// DefaultQuota is the per-project quota on the prefix space
    60  	// that can be allocated from the subnetpool for project subnets.
    61  	DefaultQuota int `json:"default_quota"`
    62  
    63  	// TenantID is the id of the Identity project.
    64  	TenantID string `json:"tenant_id"`
    65  
    66  	// ProjectID is the id of the Identity project.
    67  	ProjectID string `json:"project_id"`
    68  
    69  	// CreatedAt is the time at which subnetpool has been created.
    70  	CreatedAt time.Time `json:"-"`
    71  
    72  	// UpdatedAt is the time at which subnetpool has been created.
    73  	UpdatedAt time.Time `json:"-"`
    74  
    75  	// Prefixes is the list of subnet prefixes to assign to the subnetpool.
    76  	// Neutron API merges adjacent prefixes and treats them as a single prefix.
    77  	// Each subnet prefix must be unique among all subnet prefixes in all subnetpools
    78  	// that are associated with the address scope.
    79  	Prefixes []string `json:"prefixes"`
    80  
    81  	// DefaultPrefixLen is yhe size of the prefix to allocate when the cidr
    82  	// or prefixlen attributes are omitted when you create the subnet.
    83  	// Defaults to the MinPrefixLen.
    84  	DefaultPrefixLen int `json:"-"`
    85  
    86  	// MinPrefixLen is the smallest prefix that can be allocated from a subnetpool.
    87  	// For IPv4 subnetpools, default is 8.
    88  	// For IPv6 subnetpools, default is 64.
    89  	MinPrefixLen int `json:"-"`
    90  
    91  	// MaxPrefixLen is the maximum prefix size that can be allocated from the subnetpool.
    92  	// For IPv4 subnetpools, default is 32.
    93  	// For IPv6 subnetpools, default is 128.
    94  	MaxPrefixLen int `json:"-"`
    95  
    96  	// AddressScopeID is the Neutron address scope to assign to the subnetpool.
    97  	AddressScopeID string `json:"address_scope_id"`
    98  
    99  	// IPversion is the IP protocol version.
   100  	// Valid value is 4 or 6. Default is 4.
   101  	IPversion int `json:"ip_version"`
   102  
   103  	// Shared indicates whether this network is shared across all projects.
   104  	Shared bool `json:"shared"`
   105  
   106  	// Description is thehuman-readable description for the resource.
   107  	Description string `json:"description"`
   108  
   109  	// IsDefault indicates if the subnetpool is default pool or not.
   110  	IsDefault bool `json:"is_default"`
   111  
   112  	// RevisionNumber is the revision number of the subnetpool.
   113  	RevisionNumber int `json:"revision_number"`
   114  
   115  	// Tags optionally set via extensions/attributestags
   116  	Tags []string `json:"tags"`
   117  }
   118  
   119  func (r *SubnetPool) UnmarshalJSON(b []byte) error {
   120  	type tmp SubnetPool
   121  
   122  	// Support for older neutron time format
   123  	var s1 struct {
   124  		tmp
   125  		DefaultPrefixLen interface{} `json:"default_prefixlen"`
   126  		MinPrefixLen     interface{} `json:"min_prefixlen"`
   127  		MaxPrefixLen     interface{} `json:"max_prefixlen"`
   128  
   129  		CreatedAt gophercloud.JSONRFC3339NoZ `json:"created_at"`
   130  		UpdatedAt gophercloud.JSONRFC3339NoZ `json:"updated_at"`
   131  	}
   132  
   133  	err := json.Unmarshal(b, &s1)
   134  	if err == nil {
   135  		*r = SubnetPool(s1.tmp)
   136  
   137  		r.CreatedAt = time.Time(s1.CreatedAt)
   138  		r.UpdatedAt = time.Time(s1.UpdatedAt)
   139  
   140  		switch t := s1.DefaultPrefixLen.(type) {
   141  		case string:
   142  			if r.DefaultPrefixLen, err = strconv.Atoi(t); err != nil {
   143  				return err
   144  			}
   145  		case float64:
   146  			r.DefaultPrefixLen = int(t)
   147  		default:
   148  			return fmt.Errorf("DefaultPrefixLen has unexpected type: %T", t)
   149  		}
   150  
   151  		switch t := s1.MinPrefixLen.(type) {
   152  		case string:
   153  			if r.MinPrefixLen, err = strconv.Atoi(t); err != nil {
   154  				return err
   155  			}
   156  		case float64:
   157  			r.MinPrefixLen = int(t)
   158  		default:
   159  			return fmt.Errorf("MinPrefixLen has unexpected type: %T", t)
   160  		}
   161  
   162  		switch t := s1.MaxPrefixLen.(type) {
   163  		case string:
   164  			if r.MaxPrefixLen, err = strconv.Atoi(t); err != nil {
   165  				return err
   166  			}
   167  		case float64:
   168  			r.MaxPrefixLen = int(t)
   169  		default:
   170  			return fmt.Errorf("MaxPrefixLen has unexpected type: %T", t)
   171  		}
   172  
   173  		return nil
   174  	}
   175  
   176  	// Support for newer neutron time format
   177  	var s2 struct {
   178  		tmp
   179  		DefaultPrefixLen interface{} `json:"default_prefixlen"`
   180  		MinPrefixLen     interface{} `json:"min_prefixlen"`
   181  		MaxPrefixLen     interface{} `json:"max_prefixlen"`
   182  
   183  		CreatedAt time.Time `json:"created_at"`
   184  		UpdatedAt time.Time `json:"updated_at"`
   185  	}
   186  
   187  	err = json.Unmarshal(b, &s2)
   188  	if err != nil {
   189  		return err
   190  	}
   191  
   192  	*r = SubnetPool(s2.tmp)
   193  
   194  	r.CreatedAt = time.Time(s2.CreatedAt)
   195  	r.UpdatedAt = time.Time(s2.UpdatedAt)
   196  
   197  	switch t := s2.DefaultPrefixLen.(type) {
   198  	case string:
   199  		if r.DefaultPrefixLen, err = strconv.Atoi(t); err != nil {
   200  			return err
   201  		}
   202  	case float64:
   203  		r.DefaultPrefixLen = int(t)
   204  	default:
   205  		return fmt.Errorf("DefaultPrefixLen has unexpected type: %T", t)
   206  	}
   207  
   208  	switch t := s2.MinPrefixLen.(type) {
   209  	case string:
   210  		if r.MinPrefixLen, err = strconv.Atoi(t); err != nil {
   211  			return err
   212  		}
   213  	case float64:
   214  		r.MinPrefixLen = int(t)
   215  	default:
   216  		return fmt.Errorf("MinPrefixLen has unexpected type: %T", t)
   217  	}
   218  
   219  	switch t := s2.MaxPrefixLen.(type) {
   220  	case string:
   221  		if r.MaxPrefixLen, err = strconv.Atoi(t); err != nil {
   222  			return err
   223  		}
   224  	case float64:
   225  		r.MaxPrefixLen = int(t)
   226  	default:
   227  		return fmt.Errorf("MaxPrefixLen has unexpected type: %T", t)
   228  	}
   229  
   230  	return nil
   231  }
   232  
   233  // SubnetPoolPage stores a single page of SubnetPools from a List() API call.
   234  type SubnetPoolPage struct {
   235  	pagination.LinkedPageBase
   236  }
   237  
   238  // NextPageURL is invoked when a paginated collection of subnetpools has reached
   239  // the end of a page and the pager seeks to traverse over a new one.
   240  // In order to do this, it needs to construct the next page's URL.
   241  func (r SubnetPoolPage) NextPageURL() (string, error) {
   242  	var s struct {
   243  		Links []gophercloud.Link `json:"subnetpools_links"`
   244  	}
   245  	err := r.ExtractInto(&s)
   246  	if err != nil {
   247  		return "", err
   248  	}
   249  	return gophercloud.ExtractNextURL(s.Links)
   250  }
   251  
   252  // IsEmpty determines whether or not a SubnetPoolPage is empty.
   253  func (r SubnetPoolPage) IsEmpty() (bool, error) {
   254  	if r.StatusCode == 204 {
   255  		return true, nil
   256  	}
   257  
   258  	subnetpools, err := ExtractSubnetPools(r)
   259  	return len(subnetpools) == 0, err
   260  }
   261  
   262  // ExtractSubnetPools interprets the results of a single page from a List() API call,
   263  // producing a slice of SubnetPools structs.
   264  func ExtractSubnetPools(r pagination.Page) ([]SubnetPool, error) {
   265  	var s struct {
   266  		SubnetPools []SubnetPool `json:"subnetpools"`
   267  	}
   268  	err := (r.(SubnetPoolPage)).ExtractInto(&s)
   269  	return s.SubnetPools, err
   270  }