github.com/chnsz/golangsdk@v0.0.0-20240506093406-85a3fbfa605b/openstack/networking/v1/subnets/requests.go (about)

     1  package subnets
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/chnsz/golangsdk"
     7  	"github.com/chnsz/golangsdk/pagination"
     8  )
     9  
    10  // ListOpts allows the filtering and sorting of paginated collections through
    11  // the API. Filtering is achieved by passing in struct field values that map to
    12  // the floating IP attributes you want to see returned. SortKey allows you to
    13  // sort by a particular network attribute. SortDir sets the direction, and is
    14  // either `asc' or `desc'. Marker and Limit are used for pagination.
    15  
    16  type ListOpts struct {
    17  	// ID is the unique identifier for the subnet.
    18  	ID string `json:"id"`
    19  
    20  	// Name is the human readable name for the subnet. It does not have to be
    21  	// unique.
    22  	Name string `json:"name"`
    23  
    24  	//Specifies the network segment on which the subnet resides.
    25  	CIDR string `json:"cidr"`
    26  
    27  	// Status indicates whether or not a subnet is currently operational.
    28  	Status string `json:"status"`
    29  
    30  	//Specifies the gateway of the subnet.
    31  	GatewayIP string `json:"gateway_ip"`
    32  
    33  	//Specifies the IP address of DNS server 1 on the subnet.
    34  	PRIMARY_DNS string `json:"primary_dns"`
    35  
    36  	//Specifies the IP address of DNS server 2 on the subnet.
    37  	SECONDARY_DNS string `json:"secondary_dns"`
    38  
    39  	//Identifies the availability zone (AZ) to which the subnet belongs.
    40  	AvailabilityZone string `json:"availability_zone"`
    41  
    42  	//Specifies the ID of the VPC to which the subnet belongs.
    43  	VPC_ID string `q:"vpc_id"`
    44  
    45  	//Specifies tags subnets must match (returning those matching all tags).
    46  	Tags string `q:"tags"`
    47  
    48  	//Specifies tags subnets must match (returning those matching at least one of the tags).
    49  	TagsAny string `q:"tags-any"`
    50  
    51  	//Specifies tags subnets mustn't match (returning those missing all tags).
    52  	NotTags string `q:"not-tags"`
    53  
    54  	//Specifies tags subnets mustn't match (returning those missing at least one of the tags).
    55  	NotTagsAny string `q:"not-tags-any"`
    56  }
    57  
    58  func (opts ListOpts) hasQueryParameter() bool {
    59  	return opts.VPC_ID != "" || opts.Tags != "" || opts.TagsAny != "" || opts.NotTags != "" || opts.NotTagsAny != ""
    60  }
    61  
    62  // ToSubnetListQuery formats a ListOpts into a query string
    63  func (opts ListOpts) ToSubnetListQuery() (string, error) {
    64  	q, err := golangsdk.BuildQueryString(opts)
    65  	if err != nil {
    66  		return "", err
    67  	}
    68  	return q.String(), nil
    69  }
    70  
    71  // List returns collection of
    72  // subnets. It accepts a ListOpts struct, which allows you to filter and sort
    73  // the returned collection for greater efficiency.
    74  //
    75  // Default policy settings return only those subnets that are owned by the
    76  // tenant who submits the request, unless an admin user submits the request.
    77  func List(c *golangsdk.ServiceClient, opts ListOpts) ([]Subnet, error) {
    78  	url := rootURL(c)
    79  
    80  	if opts.hasQueryParameter() {
    81  		query, err := opts.ToSubnetListQuery()
    82  		if err != nil {
    83  			return nil, err
    84  		}
    85  		url += query
    86  	}
    87  
    88  	pages, err := pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
    89  		return SubnetPage{pagination.LinkedPageBase{PageResult: r}}
    90  	}).AllPages()
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	allSubnets, err := ExtractSubnets(pages)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  
   100  	return FilterSubnets(allSubnets, opts)
   101  }
   102  
   103  func FilterSubnets(subnets []Subnet, opts ListOpts) ([]Subnet, error) {
   104  
   105  	var refinedSubnets []Subnet
   106  	var matched bool
   107  	m := map[string]interface{}{}
   108  
   109  	if opts.ID != "" {
   110  		m["ID"] = opts.ID
   111  	}
   112  	if opts.Name != "" {
   113  		m["Name"] = opts.Name
   114  	}
   115  	if opts.CIDR != "" {
   116  		m["CIDR"] = opts.CIDR
   117  	}
   118  	if opts.Status != "" {
   119  		m["Status"] = opts.Status
   120  	}
   121  	if opts.GatewayIP != "" {
   122  		m["GatewayIP"] = opts.GatewayIP
   123  	}
   124  	if opts.PRIMARY_DNS != "" {
   125  		m["PRIMARY_DNS"] = opts.PRIMARY_DNS
   126  	}
   127  	if opts.SECONDARY_DNS != "" {
   128  		m["SECONDARY_DNS"] = opts.SECONDARY_DNS
   129  	}
   130  	if opts.AvailabilityZone != "" {
   131  		m["AvailabilityZone"] = opts.AvailabilityZone
   132  	}
   133  	if opts.VPC_ID != "" {
   134  		m["VPC_ID"] = opts.VPC_ID
   135  	}
   136  
   137  	if len(m) > 0 && len(subnets) > 0 {
   138  		for _, subnet := range subnets {
   139  			matched = true
   140  
   141  			for key, value := range m {
   142  				if sVal := getStructField(&subnet, key); !(sVal == value) {
   143  					matched = false
   144  				}
   145  			}
   146  
   147  			if matched {
   148  				refinedSubnets = append(refinedSubnets, subnet)
   149  			}
   150  		}
   151  
   152  	} else {
   153  		refinedSubnets = subnets
   154  	}
   155  
   156  	return refinedSubnets, nil
   157  }
   158  
   159  func getStructField(v *Subnet, field string) string {
   160  	r := reflect.ValueOf(v)
   161  	f := reflect.Indirect(r).FieldByName(field)
   162  	return string(f.String())
   163  }
   164  
   165  // CreateOptsBuilder allows extensions to add additional parameters to the
   166  // Create request.
   167  type CreateOptsBuilder interface {
   168  	ToSubnetCreateMap() (map[string]interface{}, error)
   169  }
   170  
   171  // CreateOpts contains all the values needed to create a new subnets. There are
   172  // no required values.
   173  type CreateOpts struct {
   174  	Name             string         `json:"name" required:"true"`
   175  	CIDR             string         `json:"cidr" required:"true"`
   176  	VPC_ID           string         `json:"vpc_id" required:"true"`
   177  	GatewayIP        string         `json:"gateway_ip" required:"true"`
   178  	EnableIPv6       *bool          `json:"ipv6_enable,omitempty"`
   179  	EnableDHCP       bool           `json:"dhcp_enable" no_default:"y"`
   180  	PRIMARY_DNS      string         `json:"primary_dns,omitempty"`
   181  	SECONDARY_DNS    string         `json:"secondary_dns,omitempty"`
   182  	DnsList          []string       `json:"dnsList,omitempty"`
   183  	AvailabilityZone string         `json:"availability_zone,omitempty"`
   184  	Description      string         `json:"description,omitempty"`
   185  	ExtraDhcpOpts    []ExtraDhcpOpt `json:"extra_dhcp_opts,omitempty"`
   186  }
   187  
   188  type ExtraDhcpOpt struct {
   189  	OptName  string  `json:"opt_name" required:"true"`
   190  	OptValue *string `json:"opt_value"`
   191  }
   192  
   193  // ToSubnetCreateMap builds a create request body from CreateOpts.
   194  func (opts CreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) {
   195  	return golangsdk.BuildRequestBody(opts, "subnet")
   196  }
   197  
   198  // Create accepts a CreateOpts struct and uses the values to create a new
   199  // logical subnets. When it is created, the subnets does not have an internal
   200  // interface - it is not associated to any subnet.
   201  //
   202  func Create(c *golangsdk.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
   203  	b, err := opts.ToSubnetCreateMap()
   204  	if err != nil {
   205  		r.Err = err
   206  		return
   207  	}
   208  	reqOpt := &golangsdk.RequestOpts{OkCodes: []int{200}}
   209  	_, r.Err = c.Post(rootURL(c), b, &r.Body, reqOpt)
   210  	return
   211  }
   212  
   213  // Get retrieves a particular subnets based on its unique ID.
   214  func Get(c *golangsdk.ServiceClient, id string) (r GetResult) {
   215  	_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
   216  	return
   217  }
   218  
   219  // UpdateOptsBuilder allows extensions to add additional parameters to the
   220  // Update request.
   221  type UpdateOptsBuilder interface {
   222  	//ToSubnetUpdateMap() (map[string]interface{}, error)
   223  	ToSubnetUpdateMap() (map[string]interface{}, error)
   224  }
   225  
   226  // UpdateOpts contains the values used when updating a subnets.
   227  type UpdateOpts struct {
   228  	Name          string         `json:"name,omitempty"`
   229  	Description   *string        `json:"description,omitempty"`
   230  	EnableIPv6    *bool          `json:"ipv6_enable,omitempty"`
   231  	EnableDHCP    bool           `json:"dhcp_enable"`
   232  	PRIMARY_DNS   string         `json:"primary_dns,omitempty"`
   233  	SECONDARY_DNS string         `json:"secondary_dns,omitempty"`
   234  	DnsList       *[]string      `json:"dnsList,omitempty"`
   235  	ExtraDhcpOpts []ExtraDhcpOpt `json:"extra_dhcp_opts,omitempty"`
   236  }
   237  
   238  // ToSubnetUpdateMap builds an update body based on UpdateOpts.
   239  func (opts UpdateOpts) ToSubnetUpdateMap() (map[string]interface{}, error) {
   240  	return golangsdk.BuildRequestBody(opts, "subnet")
   241  }
   242  
   243  // Update allows subnets to be updated. You can update the name, administrative
   244  // state, and the external gateway.
   245  func Update(c *golangsdk.ServiceClient, vpcid string, id string, opts UpdateOptsBuilder) (r UpdateResult) {
   246  	b, err := opts.ToSubnetUpdateMap()
   247  	if err != nil {
   248  		r.Err = err
   249  		return
   250  	}
   251  	_, r.Err = c.Put(updateURL(c, vpcid, id), b, &r.Body, &golangsdk.RequestOpts{
   252  		OkCodes: []int{200},
   253  	})
   254  	return
   255  }
   256  
   257  // Delete will permanently delete a particular subnets based on its unique ID.
   258  func Delete(c *golangsdk.ServiceClient, vpcid string, id string) (r DeleteResult) {
   259  	_, r.Err = c.Delete(updateURL(c, vpcid, id), nil)
   260  	return
   261  }