1package groups 2 3import ( 4 "encoding/json" 5 "time" 6 7 "github.com/gophercloud/gophercloud" 8 "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules" 9 "github.com/gophercloud/gophercloud/pagination" 10) 11 12// SecGroup represents a container for security group rules. 13type SecGroup struct { 14 // The UUID for the security group. 15 ID string 16 17 // Human-readable name for the security group. Might not be unique. 18 // Cannot be named "default" as that is automatically created for a tenant. 19 Name string 20 21 // The security group description. 22 Description string 23 24 // A slice of security group rules that dictate the permitted behaviour for 25 // traffic entering and leaving the group. 26 Rules []rules.SecGroupRule `json:"security_group_rules"` 27 28 // TenantID is the project owner of the security group. 29 TenantID string `json:"tenant_id"` 30 31 // UpdatedAt and CreatedAt contain ISO-8601 timestamps of when the state of the 32 // security group last changed, and when it was created. 33 UpdatedAt time.Time `json:"-"` 34 CreatedAt time.Time `json:"-"` 35 36 // ProjectID is the project owner of the security group. 37 ProjectID string `json:"project_id"` 38 39 // Tags optionally set via extensions/attributestags 40 Tags []string `json:"tags"` 41} 42 43func (r *SecGroup) UnmarshalJSON(b []byte) error { 44 type tmp SecGroup 45 46 // Support for older neutron time format 47 var s1 struct { 48 tmp 49 CreatedAt gophercloud.JSONRFC3339NoZ `json:"created_at"` 50 UpdatedAt gophercloud.JSONRFC3339NoZ `json:"updated_at"` 51 } 52 53 err := json.Unmarshal(b, &s1) 54 if err == nil { 55 *r = SecGroup(s1.tmp) 56 r.CreatedAt = time.Time(s1.CreatedAt) 57 r.UpdatedAt = time.Time(s1.UpdatedAt) 58 59 return nil 60 } 61 62 // Support for newer neutron time format 63 var s2 struct { 64 tmp 65 CreatedAt time.Time `json:"created_at"` 66 UpdatedAt time.Time `json:"updated_at"` 67 } 68 69 err = json.Unmarshal(b, &s2) 70 if err != nil { 71 return err 72 } 73 74 *r = SecGroup(s2.tmp) 75 r.CreatedAt = time.Time(s2.CreatedAt) 76 r.UpdatedAt = time.Time(s2.UpdatedAt) 77 78 return nil 79} 80 81// SecGroupPage is the page returned by a pager when traversing over a 82// collection of security groups. 83type SecGroupPage struct { 84 pagination.LinkedPageBase 85} 86 87// NextPageURL is invoked when a paginated collection of security groups has 88// reached the end of a page and the pager seeks to traverse over a new one. In 89// order to do this, it needs to construct the next page's URL. 90func (r SecGroupPage) NextPageURL() (string, error) { 91 var s struct { 92 Links []gophercloud.Link `json:"security_groups_links"` 93 } 94 err := r.ExtractInto(&s) 95 if err != nil { 96 return "", err 97 } 98 99 return gophercloud.ExtractNextURL(s.Links) 100} 101 102// IsEmpty checks whether a SecGroupPage struct is empty. 103func (r SecGroupPage) IsEmpty() (bool, error) { 104 is, err := ExtractGroups(r) 105 return len(is) == 0, err 106} 107 108// ExtractGroups accepts a Page struct, specifically a SecGroupPage struct, 109// and extracts the elements into a slice of SecGroup structs. In other words, 110// a generic collection is mapped into a relevant slice. 111func ExtractGroups(r pagination.Page) ([]SecGroup, error) { 112 var s struct { 113 SecGroups []SecGroup `json:"security_groups"` 114 } 115 err := (r.(SecGroupPage)).ExtractInto(&s) 116 return s.SecGroups, err 117} 118 119type commonResult struct { 120 gophercloud.Result 121} 122 123// Extract is a function that accepts a result and extracts a security group. 124func (r commonResult) Extract() (*SecGroup, error) { 125 var s struct { 126 SecGroup *SecGroup `json:"security_group"` 127 } 128 err := r.ExtractInto(&s) 129 return s.SecGroup, err 130} 131 132// CreateResult represents the result of a create operation. Call its Extract 133// method to interpret it as a SecGroup. 134type CreateResult struct { 135 commonResult 136} 137 138// UpdateResult represents the result of an update operation. Call its Extract 139// method to interpret it as a SecGroup. 140type UpdateResult struct { 141 commonResult 142} 143 144// GetResult represents the result of a get operation. Call its Extract 145// method to interpret it as a SecGroup. 146type GetResult struct { 147 commonResult 148} 149 150// DeleteResult represents the result of a delete operation. Call its 151// ExtractErr method to determine if the request succeeded or failed. 152type DeleteResult struct { 153 gophercloud.ErrResult 154} 155