Skip to content

Commit

Permalink
Add ovh_iploadbalancing_http_route_rule
Browse files Browse the repository at this point in the history
  • Loading branch information
Elie CHARRA committed Jun 1, 2018
1 parent d47a944 commit 845a891
Show file tree
Hide file tree
Showing 4 changed files with 429 additions and 0 deletions.
1 change: 1 addition & 0 deletions ovh/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func Provider() terraform.ResourceProvider {
"ovh_iploadbalancing_tcp_farm": resourceIpLoadbalancingTcpFarm(),
"ovh_iploadbalancing_tcp_farm_server": resourceIpLoadbalancingTcpFarmServer(),
"ovh_iploadbalancing_http_route": resourceIPLoadbalancingRouteHTTP(),
"ovh_iploadbalancing_http_route_rule": resourceIPLoadbalancingRouteHTTPRule(),
"ovh_domain_zone_record": resourceOvhDomainZoneRecord(),
"ovh_domain_zone_redirection": resourceOvhDomainZoneRedirection(),
// New naming schema (issue #23)
Expand Down
155 changes: 155 additions & 0 deletions ovh/resource_ovh_iploadbalancing_http_route_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package ovh

import (
"fmt"

"github.com/hashicorp/terraform/helper/schema"
)

//IPLoadbalancingRouteHTTPRule HTTP Route Rule
type IPLoadbalancingRouteHTTPRule struct {
RuleID int `json:"ruleId,omitempty"` //Id of your rule
RouteID int `json:"routeId,omitempty"` //Id of your route
DisplayName string `json:"displayName,omitempty"` //Human readable name for your rule
Field string `json:"field,omitempty"` //Name of the field to match like "protocol" or "host". See "/ipLoadbalancing/{serviceName}/availableRouteRules" for a list of available rules
Match string `json:"match,omitempty"` //Matching operator. Not all operators are available for all fields. See "/ipLoadbalancing/{serviceName}/availableRouteRules"
Negate bool `json:"negate,omitempty"` //Invert the matching operator effect
Pattern string `json:"pattern,omitempty"` //Value to match against this match. Interpretation if this field depends on the match and field
SubField string `json:"subField,omitempty"` //Name of sub-field, if applicable. This may be a Cookie or Header name for instance
}

func resourceIPLoadbalancingRouteHTTPRule() *schema.Resource {
return &schema.Resource{
Create: resourceIPLoadbalancingRouteHTTPRuleCreate,
Read: resourceIPLoadbalancingRouteHTTPRuleRead,
Update: resourceIPLoadbalancingRouteHTTPRuleUpdate,
Delete: resourceIPLoadbalancingRouteHTTPRuleDelete,

Schema: map[string]*schema.Schema{
"service_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"route_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"display_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"field": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"match": &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
err := validateStringEnum(v.(string), []string{"contains", "endswith", "exists", "in", "internal", "is", "matches", "startswith"})
if err != nil {
errors = append(errors, err)
}
return
},
},
"negate": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
"pattern": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"sub_field": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
},
}
}

func resourceIPLoadbalancingRouteHTTPRuleCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

rule := &IPLoadbalancingRouteHTTPRule{
DisplayName: d.Get("display_name").(string),
Field: d.Get("field").(string),
Match: d.Get("match").(string),
Negate: d.Get("negate").(bool),
Pattern: d.Get("pattern").(string),
SubField: d.Get("sub_field").(string),
}

service := d.Get("service_name").(string)
routeID := d.Get("route_id").(string)
resp := &IPLoadbalancingRouteHTTPRule{}
endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s/rule", service, routeID)

err := config.OVHClient.Post(endpoint, rule, resp)
if err != nil {
return fmt.Errorf("calling POST %s :\n\t %s", endpoint, err.Error())
}

d.SetId(fmt.Sprintf("%d", resp.RuleID))

return nil
}

func resourceIPLoadbalancingRouteHTTPRuleRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
service := d.Get("service_name").(string)
routeID := d.Get("route_id").(string)
r := &IPLoadbalancingRouteHTTPRule{}
endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s/rule/%s", service, routeID, d.Id())

err := config.OVHClient.Get(endpoint, &r)
if err != nil {
return CheckDeleted(d, err, endpoint)
}

return nil
}

func resourceIPLoadbalancingRouteHTTPRuleUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
service := d.Get("service_name").(string)
routeID := d.Get("route_id").(string)

endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s/rule/%s", service, routeID, d.Id())

rule := &IPLoadbalancingRouteHTTPRule{
DisplayName: d.Get("display_name").(string),
Field: d.Get("field").(string),
Match: d.Get("match").(string),
Negate: d.Get("negate").(bool),
Pattern: d.Get("pattern").(string),
SubField: d.Get("sub_field").(string),
}

err := config.OVHClient.Put(endpoint, rule, nil)
if err != nil {
return fmt.Errorf("calling %s:\n\t %s", endpoint, err.Error())
}

return nil
}

func resourceIPLoadbalancingRouteHTTPRuleDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

service := d.Get("service_name").(string)
routeID := d.Get("route_id").(string)

r := &IPLoadbalancingRouteHTTPRule{}
endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s/rule/%s", service, routeID, d.Id())

err := config.OVHClient.Delete(endpoint, &r)
if err != nil {
return fmt.Errorf("Error calling %s: %s \n", endpoint, err.Error())
}

return nil
}
192 changes: 192 additions & 0 deletions ovh/resource_ovh_iploadbalancing_http_route_rule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package ovh

import (
"bytes"
"fmt"
"os"
"reflect"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

var TestAccIPLoadbalancingRouteHTTPRulePlan = [][]map[string]interface{}{
{
{"DisplayName": "Test rule", "Field": "header", "Match": "is", "Negate": false, "Pattern": "example.com", "SubField": "Host"},
},
}

type TestAccIPLoadbalancingRouteHTTPRule struct {
ServiceName string
RuleID int `json:"ruleId"`
RouteID int `json:"routeId"`
DisplayName string `json:"displayName"`
Field string `json:"field"`
Match string `json:"match"`
Negate bool `json:"negate"`
Pattern string `json:"pattern"`
SubField string `json:"subField"`
}

type TestAccIPLoadbalancingRouteHTTPRuleWrapper struct {
Expected *TestAccIPLoadbalancingRouteHTTPRule
}

func (w *TestAccIPLoadbalancingRouteHTTPRuleWrapper) Config() string {
var config bytes.Buffer
config.WriteString(fmt.Sprintf(`
resource "ovh_iploadbalancing_http_route" "testroute" {
service_name = "%s"
display_name = "Test route"
weight = 0
action {
status = 302
target = "http://example.com"
type = "redirect"
}
}
resource "ovh_iploadbalancing_http_route_rule" "testrule" {
service_name = "%s"
route_id = "${ovh_iploadbalancing_http_route.testroute.id}"
display_name = "%s"
field = "%s"
match = "%s"
negate = %t
pattern = "%s"
sub_field = "%s"
}
`, w.Expected.ServiceName,
w.Expected.ServiceName,
w.Expected.DisplayName,
w.Expected.Field,
w.Expected.Match,
w.Expected.Negate,
w.Expected.Pattern,
w.Expected.SubField))

return config.String()
}

func (rule *TestAccIPLoadbalancingRouteHTTPRule) MustEqual(compared *TestAccIPLoadbalancingRouteHTTPRule) error {
if !reflect.DeepEqual(rule.DisplayName, compared.DisplayName) {
return fmt.Errorf("DisplayName differs")
}
if !reflect.DeepEqual(rule.Field, compared.Field) {
return fmt.Errorf("Field differs")
}
if !reflect.DeepEqual(rule.Match, compared.Match) {
return fmt.Errorf("Match differs")
}
if !reflect.DeepEqual(rule.Negate, compared.Negate) {
return fmt.Errorf("Negate differs")
}
if !reflect.DeepEqual(rule.Pattern, compared.Pattern) {
return fmt.Errorf("Pattern differs")
}
if !reflect.DeepEqual(rule.SubField, compared.SubField) {
return fmt.Errorf("SubField differs")
}

return nil
}

type TestAccIPLoadbalancingRouteHTTPRuleStep struct {
Response *TestAccIPLoadbalancingRouteHTTPRule
Expected *TestAccIPLoadbalancingRouteHTTPRule
}

func (w *TestAccIPLoadbalancingRouteHTTPRuleWrapper) TestStep(c map[string]interface{}) resource.TestStep {
if val, ok := c["DisplayName"]; ok {
w.Expected.DisplayName = val.(string)
}
if val, ok := c["Field"]; ok {
w.Expected.Field = val.(string)
}
if val, ok := c["Match"]; ok {
w.Expected.Match = val.(string)
}
if val, ok := c["Negate"]; ok {
w.Expected.Negate = val.(bool)
}
if val, ok := c["Pattern"]; ok {
w.Expected.Pattern = val.(string)
}
if val, ok := c["SubField"]; ok {
w.Expected.SubField = val.(string)
}
expected := *w.Expected

return resource.TestStep{
Config: w.Config(),
Check: resource.ComposeTestCheckFunc(
w.TestCheck(expected),
),
}
}

func (w *TestAccIPLoadbalancingRouteHTTPRuleWrapper) TestCheck(expected TestAccIPLoadbalancingRouteHTTPRule) resource.TestCheckFunc {
return func(state *terraform.State) error {
response := &TestAccIPLoadbalancingRouteHTTPRule{}
name := "ovh_iploadbalancing_http_route_rule.testrule"
resource, ok := state.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
config := testAccProvider.Meta().(*Config)
endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s/rule/%s", os.Getenv("OVH_IPLB_SERVICE"), resource.Primary.Attributes["route_id"], resource.Primary.ID)
err := config.OVHClient.Get(endpoint, response)
if err != nil {
return fmt.Errorf("calling GET %s :\n\t %s", endpoint, err.Error())
}

err = expected.MustEqual(response)
if err != nil {
return fmt.Errorf("%s %s state differs from expected : %s", name, resource.Primary.ID, err.Error())
}
return nil
}
}

func (w *TestAccIPLoadbalancingRouteHTTPRuleWrapper) TestDestroy(state *terraform.State) error {
leftovers := false
for _, resource := range state.RootModule().Resources {
if resource.Type != "ovh_iploadbalancing_http_route_rule" {
continue
}

config := testAccProvider.Meta().(*Config)
endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%d/rule/%s", os.Getenv("OVH_IPLB_SERVICE"), w.Expected.RouteID, resource.Primary.ID)
err := config.OVHClient.Get(endpoint, nil)
if err == nil {
leftovers = true
}
}
if leftovers {
return fmt.Errorf("IpLoadbalancing http route rule still exists")
}
return nil
}

func newTestAccIPLoadbalancingRouteHTTPRuleWrapper() *TestAccIPLoadbalancingRouteHTTPRuleWrapper {
return &TestAccIPLoadbalancingRouteHTTPRuleWrapper{
Expected: &TestAccIPLoadbalancingRouteHTTPRule{ServiceName: os.Getenv("OVH_IPLB_SERVICE")},
}
}

func TestAccIpLoadbalancingRouteHTTPRuleBasicCreate(t *testing.T) {
for _, plan := range TestAccIPLoadbalancingRouteHTTPRulePlan {
w := newTestAccIPLoadbalancingRouteHTTPRuleWrapper()
var steps []resource.TestStep
for _, tcase := range plan {
steps = append(steps, w.TestStep(tcase))
}
resource.Test(t, resource.TestCase{
Providers: testAccProviders,
CheckDestroy: w.TestDestroy,
Steps: steps,
})
}
}
Loading

0 comments on commit 845a891

Please sign in to comment.