Skip to content

Commit

Permalink
Octavia l7 rule support - part 1: create
Browse files Browse the repository at this point in the history
  • Loading branch information
lingxiankong committed Apr 11, 2018
1 parent 92596e8 commit ce751f8
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 0 deletions.
24 changes: 24 additions & 0 deletions acceptance/openstack/loadbalancer/v2/loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,30 @@ func CreateL7Policy(t *testing.T, client *gophercloud.ServiceClient, listener *l
return policy, nil
}

// CreateL7Rule creates a l7 rule for specified l7 policy.
func CreateL7Rule(t *testing.T, client *gophercloud.ServiceClient, policyID string, lb *loadbalancers.LoadBalancer) (*l7policies.Rule, error) {
t.Logf("Attempting to create l7 rule for policy %s", policyID)

createOpts := l7policies.CreateRuleOpts{
RuleType: l7policies.TypePath,
CompareType: l7policies.CompareTypeStartWith,
Value: "/api",
}

rule, err := l7policies.CreateRule(client, policyID, createOpts).Extract()
if err != nil {
return rule, err
}

t.Logf("Successfully created l7 rule for policy %s", policyID)

if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
return rule, fmt.Errorf("Timed out waiting for loadbalancer to become active")
}

return rule, nil
}

// DeleteL7Policy will delete a specified l7 policy. A fatal error will occur if
// the l7 policy could not be deleted. This works best when used as a deferred
// function.
Expand Down
6 changes: 6 additions & 0 deletions acceptance/openstack/loadbalancer/v2/loadbalancers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ func TestLoadbalancersCRUD(t *testing.T) {

tools.PrintResource(t, newPolicy)

// L7 rule
_, err = CreateL7Rule(t, lbClient, newPolicy.ID, lb)
if err != nil {
t.Fatalf("Unable to create l7 rule: %v", err)
}

// Pool
pool, err := CreatePool(t, lbClient, lb)
if err != nil {
Expand Down
13 changes: 13 additions & 0 deletions openstack/loadbalancer/v2/l7policies/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,18 @@ Example to Update a L7Policy
if err != nil {
panic(err)
}
Example to Create a Rule
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
createOpts := l7policies.CreateRuleOpts{
RuleType: l7policies.TypePath,
CompareType: l7policies.CompareTypeRegex,
Value: "/images*",
}
rule, err := l7policies.CreateRule(lbClient, l7policyID, createOpts).Extract()
if err != nil {
panic(err)
}
*/
package l7policies
40 changes: 40 additions & 0 deletions openstack/loadbalancer/v2/l7policies/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,43 @@ func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r
})
return
}

// CreateRuleOpts is the common options struct used in this package's CreateRule
// operation.
type CreateRuleOpts struct {
// The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH.
RuleType RuleType `json:"type" required:"true"`

// The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH.
CompareType CompareType `json:"compare_type" required:"true"`

// The value to use for the comparison. For example, the file type to compare.
Value string `json:"value" required:"true"`

// TenantID is the UUID of the project who owns the rule in neutron-lbaas.
// Only administrative users can specify a project UUID other than their own.
TenantID string `json:"tenant_id,omitempty"`

// The key to use for the comparison. For example, the name of the cookie to evaluate.
Key string `json:"key,omitempty"`

// When true the logic of the rule is inverted. For example, with invert true,
// equal to would become not equal to. Default is false.
Invert bool `json:"invert,omitempty"`
}

// ToRuleCreateMap builds a request body from CreateRuleOpts.
func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "rule")
}

// CreateRule will create and associate a Rule with a particular L7Policy.
func CreateRule(c *gophercloud.ServiceClient, policyID string, opts CreateRuleOpts) (r CreateRuleResult) {
b, err := opts.ToRuleCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(ruleRootURL(c, policyID), b, &r.Body, nil)
return
}
19 changes: 19 additions & 0 deletions openstack/loadbalancer/v2/l7policies/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,22 @@ type DeleteResult struct {
type UpdateResult struct {
commonResult
}

type commonRuleResult struct {
gophercloud.Result
}

// Extract is a function that accepts a result and extracts a rule.
func (r commonRuleResult) Extract() (*Rule, error) {
var s struct {
Rule *Rule `json:"rule"`
}
err := r.ExtractInto(&s)
return s.Rule, err
}

// CreateRuleResult represents the result of a CreateRule operation.
// Call its Extract method to interpret it as a Rule.
type CreateRuleResult struct {
commonRuleResult
}
46 changes: 46 additions & 0 deletions openstack/loadbalancer/v2/l7policies/testing/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ var (
AdminStateUp: true,
Rules: []l7policies.Rule{},
}
RulePath = l7policies.Rule{
ID: "16621dbb-a736-4888-a57a-3ecd53df784c",
RuleType: "PATH",
CompareType: "REGEX",
Value: "/images*",
TenantID: "e3cd678b11784734bc366148aa37580e",
Key: "",
Invert: false,
AdminStateUp: true,
}
)

// HandleL7PolicyCreationSuccessfully sets up the test server to respond to a l7policy creation request
Expand Down Expand Up @@ -203,3 +213,39 @@ func HandleL7PolicyUpdateSuccessfully(t *testing.T) {
fmt.Fprintf(w, PostUpdateL7PolicyBody)
})
}

// SingleRuleBody is the canned body of a Get request on an existing rule.
const SingleRuleBody = `
{
"rule": {
"compare_type": "REGEX",
"invert": false,
"admin_state_up": true,
"value": "/images*",
"key": null,
"tenant_id": "e3cd678b11784734bc366148aa37580e",
"type": "PATH",
"id": "16621dbb-a736-4888-a57a-3ecd53df784c"
}
}
`

// HandleRuleCreationSuccessfully sets up the test server to respond to a rule creation request
// with a given response.
func HandleRuleCreationSuccessfully(t *testing.T, response string) {
th.Mux.HandleFunc("/v2.0/lbaas/l7policies/8a1412f0-4c32-4257-8b07-af4770b604fd/rules", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "POST")
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
th.TestJSONRequest(t, r, `{
"rule": {
"compare_type": "REGEX",
"type": "PATH",
"value": "/images*"
}
}`)

w.WriteHeader(http.StatusAccepted)
w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, response)
})
}
47 changes: 47 additions & 0 deletions openstack/loadbalancer/v2/l7policies/testing/requests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,50 @@ func TestUpdateL7Policy(t *testing.T) {

th.CheckDeepEquals(t, L7PolicyUpdated, *actual)
}

func TestCreateRule(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
HandleRuleCreationSuccessfully(t, SingleRuleBody)

actual, err := l7policies.CreateRule(fake.ServiceClient(), "8a1412f0-4c32-4257-8b07-af4770b604fd", l7policies.CreateRuleOpts{
RuleType: l7policies.TypePath,
CompareType: l7policies.CompareTypeRegex,
Value: "/images*",
}).Extract()
th.AssertNoErr(t, err)

th.CheckDeepEquals(t, RulePath, *actual)
}

func TestRequiredRuleCreateOpts(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()

res := l7policies.CreateRule(fake.ServiceClient(), "", l7policies.CreateRuleOpts{})
if res.Err == nil {
t.Fatalf("Expected error, got none")
}
res = l7policies.CreateRule(fake.ServiceClient(), "8a1412f0-4c32-4257-8b07-af4770b604fd", l7policies.CreateRuleOpts{
RuleType: l7policies.TypePath,
})
if res.Err == nil {
t.Fatalf("Expected error, but got none")
}
res = l7policies.CreateRule(fake.ServiceClient(), "8a1412f0-4c32-4257-8b07-af4770b604fd", l7policies.CreateRuleOpts{
RuleType: l7policies.RuleType("invalid"),
CompareType: l7policies.CompareTypeRegex,
Value: "/images*",
})
if res.Err == nil {
t.Fatalf("Expected error, but got none")
}
res = l7policies.CreateRule(fake.ServiceClient(), "8a1412f0-4c32-4257-8b07-af4770b604fd", l7policies.CreateRuleOpts{
RuleType: l7policies.TypePath,
CompareType: l7policies.CompareType("invalid"),
Value: "/images*",
})
if res.Err == nil {
t.Fatalf("Expected error, but got none")
}
}
5 changes: 5 additions & 0 deletions openstack/loadbalancer/v2/l7policies/urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "github.com/gophercloud/gophercloud"
const (
rootPath = "lbaas"
resourcePath = "l7policies"
rulePath = "rules"
)

func rootURL(c *gophercloud.ServiceClient) string {
Expand All @@ -14,3 +15,7 @@ func rootURL(c *gophercloud.ServiceClient) string {
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id)
}

func ruleRootURL(c *gophercloud.ServiceClient, policyID string) string {
return c.ServiceURL(rootPath, resourcePath, policyID, rulePath)
}

0 comments on commit ce751f8

Please sign in to comment.