diff --git a/ovh/helpers.go b/ovh/helpers.go index 3c2252da0..e5924bc73 100644 --- a/ovh/helpers.go +++ b/ovh/helpers.go @@ -3,6 +3,9 @@ package ovh import ( "bytes" "fmt" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/ovh/go-ovh/ovh" ) func validateStringEnum(value string, enum []string) error { @@ -62,3 +65,14 @@ func conditionalAttributeBool(buff *bytes.Buffer, name string, val *bool) { buff.WriteString(fmt.Sprintf(" %s = %v\n", name, *val)) } } + +// CheckDeleted checks the error to see if it's a 404 (Not Found) and, if so, +// sets the resource ID to the empty string instead of throwing an error. +func CheckDeleted(d *schema.ResourceData, err error, endpoint string) error { + if err.(*ovh.APIError).Code == 404 { + d.SetId("") + return nil + } + + return fmt.Errorf("calling %s:\n\t %s", endpoint, err.Error()) +} diff --git a/ovh/provider.go b/ovh/provider.go index 11a733983..31f30af81 100644 --- a/ovh/provider.go +++ b/ovh/provider.go @@ -57,6 +57,8 @@ func Provider() terraform.ResourceProvider { ResourcesMap: map[string]*schema.Resource{ "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) diff --git a/ovh/provider_test.go b/ovh/provider_test.go index 7a4c40465..9e91fe053 100644 --- a/ovh/provider_test.go +++ b/ovh/provider_test.go @@ -70,6 +70,11 @@ func testAccPreCheck(t *testing.T) { t.Fatal("OVH_ZONE must be set for acceptance tests") } + v = os.Getenv("OVH_IPLB_SERVICE") + if v == "" { + t.Fatal("OVH_IPLB_SERVICE must be set for acceptance tests") + } + if testAccOVHClient == nil { config := Config{ Endpoint: os.Getenv("OVH_ENDPOINT"), @@ -123,6 +128,26 @@ func testAccCheckPublicCloudExists(t *testing.T) { } +func testAccCheckIpLoadbalancingExists(t *testing.T) { + type iplbResponse struct { + ServiceName string `json:"serviceName"` + State string `json:"state"` + } + + r := iplbResponse{} + + endpoint := fmt.Sprintf("/ipLoadbalancing/%s", os.Getenv("OVH_IPLB_SERVICE")) + + + err := testAccOVHClient.Get(endpoint, &r) + if err != nil { + t.Fatalf("Error: %q\n", err) + } + t.Logf("Read IPLB service %s -> state: '%s', serviceName: '%s'", endpoint, r.State, r.ServiceName) + +} + + func testAccCheckDomainZoneExists(t *testing.T) { type domainZoneResponse struct { NameServers []string `json:"nameServers"` @@ -136,6 +161,7 @@ func testAccCheckDomainZoneExists(t *testing.T) { if err != nil { t.Fatalf("Error: %q\n", err) } + t.Logf("Read Domain Zone %s -> nameservers: '%v'", endpoint, r.NameServers) } diff --git a/ovh/resource_ovh_iploadbalancing_http_route.go b/ovh/resource_ovh_iploadbalancing_http_route.go new file mode 100644 index 000000000..493c2d1dc --- /dev/null +++ b/ovh/resource_ovh_iploadbalancing_http_route.go @@ -0,0 +1,167 @@ +package ovh + +import ( + "fmt" + + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceIPLoadbalancingRouteHTTP() *schema.Resource { + return &schema.Resource{ + Create: resourceIPLoadbalancingRouteHTTPCreate, + Read: resourceIPLoadbalancingRouteHTTPRead, + Update: resourceIPLoadbalancingRouteHTTPUpdate, + Delete: resourceIPLoadbalancingRouteHTTPDelete, + + Schema: map[string]*schema.Schema{ + "service_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "action": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + ForceNew: false, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "status": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + }, + "target": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "display_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, + "frontend_id": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "weight": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + }, + }, + } +} + +// IPLoadbalancingRouteHTTPAction Action triggered when all rules match +type IPLoadbalancingRouteHTTPAction struct { + Target string `json:"target,omitempty"` // Farm ID for "farm" action type or URL template for "redirect" action. You may use ${uri}, ${protocol}, ${host}, ${port} and ${path} variables in redirect target + Status int `json:"status,omitempty"` // HTTP status code for "redirect" and "reject" actions + Type string `json:"type,omitempty"` // Action to trigger if all the rules of this route matches +} + +//IPLoadbalancingRouteHTTP HTTP Route +type IPLoadbalancingRouteHTTP struct { + Status string `json:"status,omitempty"` //Route status. Routes in "ok" state are ready to operate + Weight int `json:"weight,omitempty"` //Route priority ([0..255]). 0 if null. Highest priority routes are evaluated first. Only the first matching route will trigger an action + Action *IPLoadbalancingRouteHTTPAction `json:"action,omitempty"` //Action triggered when all rules match + RouteID int `json:"routeId,omitempty"` //Id of your route + DisplayName string `json:"displayName,omitempty"` //Human readable name for your route, this field is for you + FrontendID int `json:"frontendId,omitempty"` //Route traffic for this frontend +} + +func resourceIPLoadbalancingRouteHTTPCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + action := &IPLoadbalancingRouteHTTPAction{} + actionSet := d.Get("action").(*schema.Set).List()[0].(map[string]interface{}) + + action.Status = actionSet["status"].(int) + action.Target = actionSet["target"].(string) + action.Type = actionSet["type"].(string) + + route := &IPLoadbalancingRouteHTTP{ + Action: action, + DisplayName: d.Get("display_name").(string), + FrontendID: d.Get("frontend_id").(int), + Weight: d.Get("weight").(int), + } + + service := d.Get("service_name").(string) + resp := &IPLoadbalancingRouteHTTP{} + endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route", service) + + err := config.OVHClient.Post(endpoint, route, resp) + if err != nil { + return fmt.Errorf("calling POST %s :\n\t %s", endpoint, err.Error()) + } + + d.SetId(fmt.Sprintf("%d", resp.RouteID)) + + return resourceIPLoadbalancingRouteHTTPRead(d, meta) +} + +func resourceIPLoadbalancingRouteHTTPRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + service := d.Get("service_name").(string) + r := &IPLoadbalancingRouteHTTP{} + endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s", service, d.Id()) + + err := config.OVHClient.Get(endpoint, &r) + if err != nil { + return CheckDeleted(d, err, endpoint) + } + + d.Set("status", r.Status) + d.Set("weight", r.Weight) + d.Set("display_name", r.DisplayName) + d.Set("frontend_id", r.FrontendID) + + return nil +} + +func resourceIPLoadbalancingRouteHTTPUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + service := d.Get("service_name").(string) + endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s", service, d.Id()) + + action := &IPLoadbalancingRouteHTTPAction{} + actionSet := d.Get("action").(*schema.Set).List()[0].(map[string]interface{}) + + action.Status = actionSet["status"].(int) + action.Target = actionSet["target"].(string) + action.Type = actionSet["type"].(string) + + route := &IPLoadbalancingRouteHTTP{ + Action: action, + DisplayName: d.Get("display_name").(string), + FrontendID: d.Get("frontend_id").(int), + Weight: d.Get("weight").(int), + } + + err := config.OVHClient.Put(endpoint, route, nil) + if err != nil { + return fmt.Errorf("calling %s:\n\t %s", endpoint, err.Error()) + } + + return resourceIPLoadbalancingRouteHTTPRead(d, meta) +} + +func resourceIPLoadbalancingRouteHTTPDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + service := d.Get("service_name").(string) + r := &IPLoadbalancingRouteHTTP{} + endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s", service, d.Id()) + + err := config.OVHClient.Delete(endpoint, &r) + if err != nil { + return fmt.Errorf("Error calling %s: %s \n", endpoint, err.Error()) + } + + return nil +} diff --git a/ovh/resource_ovh_iploadbalancing_http_route_rule.go b/ovh/resource_ovh_iploadbalancing_http_route_rule.go new file mode 100644 index 000000000..874bd1c78 --- /dev/null +++ b/ovh/resource_ovh_iploadbalancing_http_route_rule.go @@ -0,0 +1,155 @@ +package ovh + +import ( + "fmt" + + "github.com/hashicorp/terraform/helper/schema" +) + +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, + }, + }, + } +} + +//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 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 resourceIPLoadbalancingRouteHTTPRuleRead(d, meta) +} + +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 resourceIPLoadbalancingRouteHTTPRuleRead(d, meta) +} + +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 +} diff --git a/ovh/resource_ovh_iploadbalancing_http_route_rule_test.go b/ovh/resource_ovh_iploadbalancing_http_route_rule_test.go new file mode 100644 index 000000000..7273a431f --- /dev/null +++ b/ovh/resource_ovh_iploadbalancing_http_route_rule_test.go @@ -0,0 +1,114 @@ +package ovh + +import ( + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccIPLoadbalancingRouteHTTPRuleBasicCreate(t *testing.T) { + serviceName := os.Getenv("OVH_IPLB_SERVICE") + displayName := "Test rule" + field := "header" + match := "is" + negate := "false" + pattern := "example.com" + subField := "Host" + + config := fmt.Sprintf( + testAccCheckOvhIpLoadbalancingHttpRouteRuleConfig_basic, + serviceName, + displayName, + field, + match, + negate, + pattern, + subField, + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccCheckIpLoadbalancingRouteHTTPRulePreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIPLoadbalancingRouteHTTPRuleDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "service_name", serviceName), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "display_name", displayName), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route_rule.testrule", "service_name", serviceName), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route_rule.testrule", "display_name", displayName), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route_rule.testrule", "field", field), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route_rule.testrule", "match", match), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route_rule.testrule", "negate", negate), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route_rule.testrule", "pattern", pattern), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route_rule.testrule", "sub_field", subField), + ), + }, + }, + }) +} + +func testAccCheckIpLoadbalancingRouteHTTPRulePreCheck(t *testing.T) { + testAccPreCheck(t) + testAccCheckIpLoadbalancingExists(t) +} + +func testAccCheckIPLoadbalancingRouteHTTPRuleDestroy(state *terraform.State) error { + 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"), + resource.Primary.Attributes["route_id"], + resource.Primary.ID, + ) + + err := config.OVHClient.Get(endpoint, nil) + if err == nil { + return fmt.Errorf("IpLoadbalancing http route rule still exists") + } + } + return nil +} + +const testAccCheckOvhIpLoadbalancingHttpRouteRuleConfig_basic = ` +resource "ovh_iploadbalancing_http_route" "testroute" { + service_name = "%s" + display_name = "%s" + weight = 0 + + action { + status = 302 + target = "http://example.com" + type = "redirect" + } +} + +resource "ovh_iploadbalancing_http_route_rule" "testrule" { + service_name = "${ovh_iploadbalancing_http_route.testroute.service_name}" + route_id = "${ovh_iploadbalancing_http_route.testroute.id}" + display_name = "${ovh_iploadbalancing_http_route.testroute.display_name}" + field = "%s" + match = "%s" + negate = %s + pattern = "%s" + sub_field = "%s" +} +` diff --git a/ovh/resource_ovh_iploadbalancing_http_route_test.go b/ovh/resource_ovh_iploadbalancing_http_route_test.go new file mode 100644 index 000000000..ce23880ed --- /dev/null +++ b/ovh/resource_ovh_iploadbalancing_http_route_test.go @@ -0,0 +1,92 @@ +package ovh + +import ( + "fmt" + "os" + "strings" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccIPLoadbalancingRouteHTTPBasicCreate(t *testing.T) { + serviceName := os.Getenv("OVH_IPLB_SERVICE") + name := "test-route-redirect-https" + weight := "0" + actionStatus := "302" + actionTarget := "https://$${host}$${path}$${arguments}" + actionType := "redirect" + + config := fmt.Sprintf( + testAccCheckOvhIpLoadbalancingHttpRouteConfig_basic, + serviceName, + name, + weight, + actionStatus, + actionTarget, + actionType, + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccCheckIpLoadbalancingRouteHTTPPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckIPLoadbalancingRouteHTTPDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "service_name", serviceName), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "display_name", name), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "weight", weight), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "action.#", "1"), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "action.859787636.status", actionStatus), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "action.859787636.target", strings.Replace(actionTarget, "$$", "$", -1)), + resource.TestCheckResourceAttr( + "ovh_iploadbalancing_http_route.testroute", "action.859787636.type", actionType), + ), + }, + }, + }) +} + +func testAccCheckIpLoadbalancingRouteHTTPPreCheck(t *testing.T) { + testAccPreCheck(t) + testAccCheckIpLoadbalancingExists(t) +} + +func testAccCheckIPLoadbalancingRouteHTTPDestroy(state *terraform.State) error { + for _, resource := range state.RootModule().Resources { + if resource.Type != "ovh_iploadbalancing_http_route" { + continue + } + + config := testAccProvider.Meta().(*Config) + endpoint := fmt.Sprintf("/ipLoadbalancing/%s/http/route/%s", os.Getenv("OVH_IPLB_SERVICE"), resource.Primary.ID) + err := config.OVHClient.Get(endpoint, nil) + if err == nil { + return fmt.Errorf("IpLoadbalancing route still exists") + } + } + return nil +} + +const testAccCheckOvhIpLoadbalancingHttpRouteConfig_basic = ` +resource "ovh_iploadbalancing_http_route" "testroute" { + service_name = "%s" + display_name = "%s" + weight = %s + + action { + status = %s + target = "%s" + type = "%s" + } +} +` diff --git a/website/docs/r/resource_ovh_iploadbalancing_http_route.markdown b/website/docs/r/resource_ovh_iploadbalancing_http_route.markdown new file mode 100644 index 000000000..c8c143c80 --- /dev/null +++ b/website/docs/r/resource_ovh_iploadbalancing_http_route.markdown @@ -0,0 +1,53 @@ +--- +layout: "ovh" +page_title: "OVH: ovh_iploadbalancing_http_route" +sidebar_current: "docs-ovh-resource-iploadbalancing-http-route" +description: |- + Manage http route for a loadbalancer service. +--- + +# ovh_iploadbalancing_http_route + +Manage http route for a loadbalancer service + +## Example Usage + +Route which redirect all url to https. + +```hcl +resource "ovh_iploadbalancing_http_route" "httpsredirect" { + service_name = "loadbalancer-xxxxxxxxxxxxxxxxxx" + display_name = "Redirect to HTTPS" + weight = 1 + + action { + status = 302 + target = "https://${host}${path}${arguments}" + type = "redirect" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `service_name` - (Required) The internal name of your IP load balancing +* `display_name` - Human readable name for your route, this field is for you +* `weight` - Route priority ([0..255]). 0 if null. Highest priority routes are evaluated first. Only the first matching route will trigger an action +* `action.status` - HTTP status code for "redirect" and "reject" actions +* `action.target` - Farm ID for "farm" action type or URL template for "redirect" action. You may use ${uri}, ${protocol}, ${host}, ${port} and ${path} variables in redirect target +* `action.type` - (Required) Action to trigger if all the rules of this route matches +* `frontend_id` - Route traffic for this frontend + +## Attributes Reference + +The following attributes are exported: + +* `service_name` - See Argument Reference above. +* `display_name` - See Argument Reference above. +* `weight` - See Argument Reference above. +* `action.status` - See Argument Reference above. +* `action.target` - See Argument Reference above. +* `action.type` - See Argument Reference above. +* `frontend_id` - See Argument Reference above. diff --git a/website/docs/r/resource_ovh_iploadbalancing_http_route_rule.markdown b/website/docs/r/resource_ovh_iploadbalancing_http_route_rule.markdown new file mode 100644 index 000000000..f08fcbacb --- /dev/null +++ b/website/docs/r/resource_ovh_iploadbalancing_http_route_rule.markdown @@ -0,0 +1,81 @@ +--- +layout: "ovh" +page_title: "OVH: ovh_iploadbalancing_http_route_rule" +sidebar_current: "docs-ovh-resource-iploadbalancing-http-route" +description: |- + Manage rules for HTTP route. +--- + +# ovh_iploadbalancing_http_route_rule + +Manage rules for HTTP route. + +## Example Usage + +Route which redirect all url to https for example.com (Vhost). + +```hcl +resource "ovh_iploadbalancing_http_route" "httpsredirect" { + service_name = "loadbalancer-xxxxxxxxxxxxxxxxxx" + display_name = "Redirect to HTTPS" + weight = 1 + frontend_id = 11111 + + action { + status = 302 + target = "https://$${host}$${path}$${arguments}" + type = "redirect" + } +} + +resource "ovh_iploadbalancing_http_route_rule" "examplerule" { + service_name = "loadbalancer-xxxxxxxxxxxxxxxxxx" + route_id = "${ovh_iploadbalancing_http_route.httpsredirect.id}" + display_name = "Match example.com host" + field = "host" + match = "is" + negate = false + pattern = "example.com" +} +``` + +Rule which match a specific header (same effect as the host match above). + +```hcl +resource "ovh_iploadbalancing_http_route_rule" "examplerule" { + service_name = "loadbalancer-xxxxxxxxxxxxxxxxxx" + route_id = "${ovh_iploadbalancing_http_route.httpsredirect.id}" + display_name = "Match example.com Host header" + field = "headers" + match = "is" + negate = false + pattern = "example.com" + sub_field = "Host" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `service_name` - (Required) The internal name of your IP load balancing +* `route_id` - (Required) The route to apply this rule +* `display_name` - Human readable name for your rule, this field is for you +* `field` - (Required) Name of the field to match like "protocol" or "host". See "/ipLoadbalancing/{serviceName}/availableRouteRules" for a list of available rules +* `match` - (Required) Matching operator. Not all operators are available for all fields. See "/ipLoadbalancing/{serviceName}/availableRouteRules" +* `negate` - Invert the matching operator effect +* `pattern` - Value to match against this match. Interpretation if this field depends on the match and field +* `sub_field` - Name of sub-field, if applicable. This may be a Cookie or Header name for instance + +## Attributes Reference + +The following attributes are exported: + +* `service_name` - See Argument Reference above. +* `route_id` - See Argument Reference above. +* `display_name` - See Argument Reference above. +* `field` - See Argument Reference above. +* `match` - See Argument Reference above. +* `negate` - See Argument Reference above. +* `pattern` - See Argument Reference above. +* `sub_field` - See Argument Reference above.