Skip to content

Commit

Permalink
Add LBaaS bindings for ACL and Rule
Browse files Browse the repository at this point in the history
  • Loading branch information
toothstone authored and Mario Schäfer committed May 19, 2022
1 parent 4ce2584 commit 1792e4b
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 2 deletions.
58 changes: 58 additions & 0 deletions pkg/apis/lbaas/v1/acl_genclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package v1

import (
"context"
"net/url"

"go.anx.io/go-anxcloud/pkg/api/types"
)

// EndpointURL returns the URL where to retrieve objects of type ACL and the identifier of the given ACL.
// It implements the api.Object interface on *ACL, making it usable with the generic API client.
func (a *ACL) EndpointURL(ctx context.Context) (*url.URL, error) {
op, err := types.OperationFromContext(ctx)
if err != nil {
return nil, err
}

u, err := url.Parse("/api/LBaaS/v1/ACL.json")
if err != nil {
return nil, err
}

if op == types.OperationList {
filters := make(url.Values)

if a.ParentType != "" {
filters.Add("parent_type", a.ParentType)
}
if a.Backend.Identifier != "" {
filters.Add("backend", a.Backend.Identifier)
}
if a.Frontend.Identifier != "" {
filters.Add("frontend", a.Frontend.Identifier)
}

query := u.Query()
query.Add("filters", filters.Encode())
u.RawQuery = query.Encode()
}

return u, nil
}

// FilterAPIRequestBody generates the request body for ACLs, replacing linked Objects with just their identifier.
func (a *ACL) FilterAPIRequestBody(ctx context.Context) (interface{}, error) {
return requestBody(ctx, func() interface{} {
return &struct {
commonRequestBody
ACL
Backend string `json:"backend,omitempty"`
Frontend string `json:"frontend,omitempty"`
}{
ACL: *a,
Backend: a.Backend.Identifier,
Frontend: a.Frontend.Identifier,
}
})
}
24 changes: 24 additions & 0 deletions pkg/apis/lbaas/v1/acl_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package v1

// anxcloud:object:hooks=RequestBodyHook

// ACL represents an LBaaS ACL
type ACL struct {
commonMethods
HasState

CustomerIdentifier string `json:"customer_identifier"`
ResellerIdentifier string `json:"reseller_identifier"`

Identifier string `json:"identifier" anxcloud:"identifier"`
Name string `json:"name"`
ParentType string `json:"parent_type"`
Criterion string `json:"criterion"`
Value string `json:"value"`
Index int `json:"index"`
AutomationRules []RuleInfo `json:"automation_rules,omitempty"`

// Only the name and identifier fields are used and returned.
Frontend Frontend `json:"frontend,omitempty"`
Backend Backend `json:"backend,omitempty"`
}
8 changes: 8 additions & 0 deletions pkg/apis/lbaas/v1/e2e_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package v1
import (
"io/ioutil"
"net/http"
"syscall"
"time"

. "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -42,3 +43,10 @@ func unavailableServerConnectionCheck(url string) {
}, 5*time.Second, 1*time.Second).Should(Succeed())
})
}

func connectionResetByPeerCheck(url string) {
It("resets connection", func() {
_, err := http.Get(url)
Expect(err).To(MatchError(syscall.ECONNRESET))
})
}
58 changes: 56 additions & 2 deletions pkg/apis/lbaas/v1/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,59 @@ import (
// Maybe we can extract some of those e2e helpers for use by other API bindings?
// -- Mara @LittleFox94 Grosch, 2022-05-03

func serverChecks(testrun LBaaSE2ETestRun, backend *Backend) {
func ruleChecks(testrun LBaaSE2ETestRun, frontend *Frontend, acl *ACL, testURL string) {
Context("with a fresh Rule", Ordered, func() {
var rule Rule

defer createObject(func() types.Object {
rule = Rule{
Name: fmt.Sprintf("go-anxcloud-%s", testrun.Name),
ParentType: "frontend",
Index: 0,
Frontend: *frontend,
Condition: "if",
ConditionTest: acl.Name,
Type: "connection",
Action: "reject",
}
return &rule
}, true)()

Context("rule blocks port", func() {
connectionResetByPeerCheck(testURL)
})

Context("rule allows port", func() {
updateObject(func() types.Object {
rule.Action = "accept"
return &rule
}, true)
successfulConnectionCheck(testURL)
})
})
}

func aclChecks(testrun LBaaSE2ETestRun, frontend *Frontend, testURL string) {
Context("with a fresh ACL", Ordered, func() {
var acl ACL

defer createObject(func() types.Object {
acl = ACL{
Name: fmt.Sprintf("go-anxcloud-%s", testrun.Name),
ParentType: "frontend",
Index: 0,
Criterion: "dst_port",
Value: fmt.Sprintf("%d", testrun.Port),
Frontend: *frontend,
}
return &acl
}, true)()

ruleChecks(testrun, frontend, &acl, testURL)
})
}

func serverChecks(testrun LBaaSE2ETestRun, backend *Backend, frontend *Frontend) {
Context("with a fresh Server", Ordered, func() {
var server Server

Expand All @@ -62,6 +114,8 @@ func serverChecks(testrun LBaaSE2ETestRun, backend *Backend) {
successfulConnectionCheck(url)
})

aclChecks(testrun, frontend, url)

Context("invalid server port", Ordered, func() {
updateObject(func() types.Object {
server.Port = 8081
Expand All @@ -86,7 +140,7 @@ func bindChecks(testrun LBaaSE2ETestRun, frontend *Frontend, backend *Backend) {
return &bind
}, true)()

serverChecks(testrun, backend)
serverChecks(testrun, backend, frontend)

updateObject(func() types.Object {
bind.Port = testrun.Port + 1
Expand Down
76 changes: 76 additions & 0 deletions pkg/apis/lbaas/v1/rule_genclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package v1

import (
"context"
"net/url"

"go.anx.io/go-anxcloud/pkg/api/types"
)

// EndpointURL returns the URL where to retrieve objects of type Rule and the identifier of the given Rule.
// It implements the api.Object interface on *Rule, making it usable with the generic API client.
func (r *Rule) EndpointURL(ctx context.Context) (*url.URL, error) {
op, err := types.OperationFromContext(ctx)
if err != nil {
return nil, err
}

u, err := url.Parse("/api/LBaaS/v1/rule.json")
if err != nil {
return nil, err
}

if op == types.OperationList {
filters := make(url.Values)

if r.RuleType != "" {
filters.Add("rule_type", r.RuleType)
}
if r.ParentType != "" {
filters.Add("parent_type", r.ParentType)
}
if r.Frontend.Identifier != "" {
filters.Add("frontend", r.Frontend.Identifier)
}
if r.Backend.Identifier != "" {
filters.Add("backend", r.Backend.Identifier)
}
if r.Condition != "" {
filters.Add("condition", r.Condition)
}
if r.Type != "" {
filters.Add("type", r.Type)
}
if r.Action != "" {
filters.Add("action", r.Action)
}
if r.RedirectionType != "" {
filters.Add("redirection_type", r.RedirectionType)
}
if r.RedirectionCode != "" {
filters.Add("redirection_code", r.RedirectionCode)
}

query := u.Query()
query.Add("filters", filters.Encode())
u.RawQuery = query.Encode()
}

return u, nil
}

// FilterAPIRequestBody generates the request body for Rules, replacing linked Objects with just their identifier.
func (r *Rule) FilterAPIRequestBody(ctx context.Context) (interface{}, error) {
return requestBody(ctx, func() interface{} {
return &struct {
commonRequestBody
Rule
Backend string `json:"backend,omitempty"`
Frontend string `json:"frontend,omitempty"`
}{
Rule: *r,
Backend: r.Backend.Identifier,
Frontend: r.Frontend.Identifier,
}
})
}
29 changes: 29 additions & 0 deletions pkg/apis/lbaas/v1/rule_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package v1

// anxcloud:object:hooks=RequestBodyHook

// Rule represents an LBaaS Rule
type Rule struct {
commonMethods
HasState

CustomerIdentifier string `json:"customer_identifier"`
ResellerIdentifier string `json:"reseller_identifier"`

Identifier string `json:"identifier" anxcloud:"identifier"`
Name string `json:"name"`
ParentType string `json:"parent_type"`
Index int `json:"index"`
Condition string `json:"condition"`
ConditionTest string `json:"condition_test"`
Type string `json:"type"`
Action string `json:"action"`
RedirectionType string `json:"redirection_type"`
RedirectionValue string `json:"redirection_value"`
RedirectionCode string `json:"redirection_code"`
RuleType string `json:"rule_type"`

// Only the name and identifier fields are used and returned.
Frontend Frontend `json:"frontend,omitempty"`
Backend Backend `json:"backend,omitempty"`
}
32 changes: 32 additions & 0 deletions pkg/apis/lbaas/v1/xxgenerated_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ import (
"go.anx.io/go-anxcloud/pkg/api/types"
)

var _ = Describe("Object ACL", func() {
o := ACL{}

ifaces := make([]interface{}, 0, 2)
{
var i types.Object
ifaces = append(ifaces, &i)
}
{
var i types.RequestBodyHook
ifaces = append(ifaces, &i)
}

testutils.ObjectTests(&o, ifaces...)
})

var _ = Describe("Object Backend", func() {
o := Backend{}

Expand Down Expand Up @@ -75,6 +91,22 @@ var _ = Describe("Object LoadBalancer", func() {
testutils.ObjectTests(&o, ifaces...)
})

var _ = Describe("Object Rule", func() {
o := Rule{}

ifaces := make([]interface{}, 0, 2)
{
var i types.Object
ifaces = append(ifaces, &i)
}
{
var i types.RequestBodyHook
ifaces = append(ifaces, &i)
}

testutils.ObjectTests(&o, ifaces...)
})

var _ = Describe("Object Server", func() {
o := Server{}

Expand Down

0 comments on commit 1792e4b

Please sign in to comment.