Skip to content

Commit

Permalink
Merge pull request #234 from albeego/master
Browse files Browse the repository at this point in the history
Adding failover IP address data and resource blocks for lookup and at…
  • Loading branch information
yanndegat authored Mar 4, 2022
2 parents b0d920c + cf80ced commit 4432c49
Show file tree
Hide file tree
Showing 12 changed files with 528 additions and 1 deletion.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Terraform OVH Provider
- [![Gitter chat](https://badges.gitter.im/hashicorp-terraform/Lobby.png)](https://gitter.im/hashicorp-terraform/Lobby)
- Mailing list: [Google Groups](http://groups.google.com/group/terraform-tool)

<img src="https://cdn.rawgit.com/hashicorp/terraform-website/master/content/source/assets/images/logo-hashicorp.svg" width="600px">
<img alt="chat on gitter" src="https://cdn.rawgit.com/hashicorp/terraform-website/master/content/source/assets/images/logo-hashicorp.svg" width="600px">

Requirements
------------
Expand Down Expand Up @@ -90,6 +90,9 @@ export OVH_IP_BLOCK_TEST="..."
export OVH_IP_REVERSE_TEST="..."
export OVH_IPLB_SERVICE_TEST="..."
export OVH_CLOUD_PROJECT_SERVICE_TEST="..."
export OVH_CLOUD_PROJECT_FAILOVER_IP_TEST="..."
export OVH_CLOUD_PROJECT_FAILOVER_IP_ROUTED_TO_1_TEST="..."
export OVH_CLOUD_PROJECT_FAILOVER_IP_ROUTED_TO_2_TEST="..."
export OVH_VRACK_SERVICE_TEST="..."
export OVH_ZONE_TEST="..."

Expand Down
14 changes: 14 additions & 0 deletions ovh/data_cloud_project_failover_ip_attach.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ovh

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceCloudProjectFailoverIpAttach() *schema.Resource {
return &schema.Resource{
Read: func(d *schema.ResourceData, meta interface{}) error {
return resourceCloudProjectFailoverIpAttachRead(d, meta)
},
Schema: resourceCloudProjectFailoverIpAttachSchema(),
}
}
57 changes: 57 additions & 0 deletions ovh/data_cloud_project_failover_ip_attach_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package ovh

import (
"fmt"
"os"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

const testAccDataSourceCloudProjectFailoverIpAttach = `
data "ovh_cloud_project_failover_ip_attach" "myfailoverip" {
service_name = "%s"
ip = "%s"
}
`

func TestAccDataSourceCloudProjectFailoverIpAttach(t *testing.T) {
serviceName := os.Getenv("OVH_CLOUD_PROJECT_SERVICE_TEST")
ipAddress := os.Getenv("OVH_CLOUD_PROJECT_FAILOVER_IP_TEST")
config := fmt.Sprintf(
testAccDataSourceCloudProjectFailoverIpAttach,
serviceName,
ipAddress,
)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheckFailoverIpAttach(t) },

Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"data.ovh_cloud_project_failover_ip_attach.myfailoverip",
"service_name",
serviceName,
),
resource.TestCheckResourceAttr(
"data.ovh_cloud_project_failover_ip_attach.myfailoverip",
"ip",
ipAddress,
),
resource.TestCheckResourceAttrSet(
"data.ovh_cloud_project_failover_ip_attach.myfailoverip",
"id",
),
resource.TestCheckResourceAttrSet(
"data.ovh_cloud_project_failover_ip_attach.myfailoverip",
"routed_to",
),
),
},
},
})
}
2 changes: 2 additions & 0 deletions ovh/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func Provider() *schema.Provider {
"ovh_cloud_project_containerregistries": dataSourceCloudProjectContainerRegistries(),
"ovh_cloud_project_containerregistry": dataSourceCloudProjectContainerRegistry(),
"ovh_cloud_project_containerregistry_users": dataSourceCloudProjectContainerRegistryUsers(),
"ovh_cloud_project_failover_ip_attach": dataSourceCloudProjectFailoverIpAttach(),
"ovh_cloud_project_kube": dataSourceCloudProjectKube(),
"ovh_cloud_project_region": dataSourceCloudProjectRegion(),
"ovh_cloud_project_regions": dataSourceCloudProjectRegions(),
Expand Down Expand Up @@ -84,6 +85,7 @@ func Provider() *schema.Provider {
"ovh_cloud_project": resourceCloudProject(),
"ovh_cloud_project_containerregistry": resourceCloudProjectContainerRegistry(),
"ovh_cloud_project_containerregistry_user": resourceCloudProjectContainerRegistryUser(),
"ovh_cloud_project_failover_ip_attach": resourceCloudProjectFailoverIpAttach(),
"ovh_cloud_project_kube": resourceCloudProjectKube(),
"ovh_cloud_project_kube_nodepool": resourceCloudProjectKubeNodePool(),
"ovh_cloud_project_network_private": resourceCloudProjectNetworkPrivate(),
Expand Down
10 changes: 10 additions & 0 deletions ovh/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,16 @@ func testAccPreCheckCloud(t *testing.T) {
checkEnvOrSkip(t, "OVH_CLOUD_PROJECT_SERVICE_TEST")
}

// Checks that the environment variables needed for the /cloud/project/{projectId}/ip/failover acceptance tests
// are set.
func testAccPreCheckFailoverIpAttach(t *testing.T) {
testAccPreCheckCredentials(t)
testAccPreCheckCloud(t)
checkEnvOrSkip(t, "OVH_CLOUD_PROJECT_FAILOVER_IP_TEST")
checkEnvOrSkip(t, "OVH_CLOUD_PROJECT_FAILOVER_IP_ROUTED_TO_1_TEST")
checkEnvOrSkip(t, "OVH_CLOUD_PROJECT_FAILOVER_IP_ROUTED_TO_2_TEST")
}

// Checks that the environment variables needed for the /cloud/{cloudId}/kube acceptance tests
// are set.
func testAccPreCheckKubernetes(t *testing.T) {
Expand Down
216 changes: 216 additions & 0 deletions ovh/resource_cloud_project_failover_ip_attach.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package ovh

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/ovh/terraform-provider-ovh/ovh/helpers"
"log"
"net/url"
)

func resourceCloudProjectFailoverIpAttach() *schema.Resource {
return &schema.Resource{
Create: resourceCloudProjectFailoverIpAttachCreate,
Read: resourceCloudProjectFailoverIpAttachRead,
Delete: resourceCloudProjectFailoverIpAttachDelete,

Importer: &schema.ResourceImporter{
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
return []*schema.ResourceData{d}, nil
},
},

Schema: resourceCloudProjectFailoverIpAttachSchema(),
}
}

func resourceCloudProjectFailoverIpAttachSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"service_name": {
Type: schema.TypeString,
Description: "The service name",
ForceNew: true,
Required: true,
},

"block": {
Type: schema.TypeString,
Description: "IP block",
Optional: true,
Computed: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
err := helpers.ValidateIp(v.(string))
if err != nil {
errors = append(errors, err)
}
return
},
},
"continent_code": {
Type: schema.TypeString,
Description: "Ip continent",
Optional: true,
Computed: true,
},
"geo_loc": {
Type: schema.TypeString,
Description: "Ip location",
Optional: true,
Computed: true,
},
"id": {
Type: schema.TypeString,
Description: "Ip id",
Computed: true,
},
"ip": {
Type: schema.TypeString,
Description: "Ip",
Optional: true,
Computed: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
err := helpers.ValidateIp(v.(string))
if err != nil {
errors = append(errors, err)
}
return
},
},
"progress": {
Type: schema.TypeInt,
Description: "Current operation progress in percent",
Computed: true,
},
"routed_to": {
Type: schema.TypeString,
Description: "Instance where ip is routed to",
Computed: true,
Optional: true,
},
"status": {
Type: schema.TypeString,
Description: "Ip status",
Computed: true,
},
"sub_type": {
Type: schema.TypeString,
Description: "IP sub type",
Computed: true,
},
}
}

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

serviceName := d.Get("service_name").(string)

log.Printf("[DEBUG] Will read cloud project ip addresses %s", serviceName)
endpoint := fmt.Sprintf("/cloud/project/%s/ip/failover",
url.PathEscape(serviceName),
)

ips := []FailoverIp{}
if err := config.OVHClient.Get(endpoint, &ips); err != nil {
return fmt.Errorf("Error calling GET %s:\n\t %q", endpoint, err)
}

match := false
for _, ip := range ips {
if ip.Ip == d.Get("ip").(string) {
for k, v := range ip.ToMap() {
match = true
if k == "id" {
d.SetId(v.(string))
} else {
err := d.Set(k, v)
if err != nil {
return err
}
}
}
}
}

if !match {
return fmt.Errorf("your query returned no results, " +
"please change your search criteria and try again")
}

return nil
}

func resourceCloudProjectFailoverIpAttachCreate(d *schema.ResourceData, meta interface{}) error {

serviceName := d.Get("service_name").(string)

config := meta.(*Config)

//Fetch Failover IP address to populate ID field
log.Printf("[DEBUG] Will read cloud project ip addresses %s", serviceName)
endpoint := fmt.Sprintf("/cloud/project/%s/ip/failover",
url.PathEscape(serviceName),
)

ips := []FailoverIp{}
if err := config.OVHClient.Get(endpoint, &ips); err != nil {
return fmt.Errorf("Error calling GET %s:\n\t %q", endpoint, err)
}

match := false
for _, ip := range ips {
if ip.Ip == d.Get("ip").(string) {
for k, v := range ip.ToMap() {
match = true
if k == "id" {
d.SetId(v.(string))
}
}
}
}

if !match {
return fmt.Errorf("your query returned no results, " +
"please change your search criteria and try again")
}

id := d.Get("id").(string)

log.Printf("[DEBUG] Will attach failover ip to an instance: %s", serviceName)
opts := (&ProjectIpFailoverAttachCreation{}).FromResource(d)
endpoint = fmt.Sprintf("/cloud/project/%s/ip/failover/%s/attach",
url.PathEscape(serviceName),
url.PathEscape(id),
)

ip := &FailoverIp{}
if err := config.OVHClient.Post(endpoint, opts, ip); err != nil {
return fmt.Errorf("calling Put %s: %q", endpoint, err)
}

for k, v := range ip.ToMap() {
match = true
if k != "id" {
err := d.Set(k, v)
if err != nil {
return err
}
}
}

for d.Get("status").(string) == "operationPending" {
if err := resourceCloudProjectFailoverIpAttachRead(d, meta); err != nil {
return err
}
}

return nil
}

func resourceCloudProjectFailoverIpAttachDelete(d *schema.ResourceData, meta interface{}) error {
// Failover IPs cannot be deleted, the best that can be done in this instance is to check it exists
if err := resourceCloudProjectFailoverIpAttachRead(d, meta); err != nil {
return err
}
return nil
}
Loading

0 comments on commit 4432c49

Please sign in to comment.