Skip to content

Commit

Permalink
Merge pull request #368 from ovh/330-workflowbackup
Browse files Browse the repository at this point in the history
Add WorkflowBackup resource
  • Loading branch information
scraly authored Feb 15, 2023
2 parents dd0a7f0 + 92972a9 commit e3dab41
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 5 deletions.
8 changes: 7 additions & 1 deletion ovh/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ package ovh

import (
"context"
ini "gopkg.in/ini.v1"
"os"
"sync"

ini "gopkg.in/ini.v1"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/mitchellh/go-homedir"
)

const (
SERVICE_NAME_ATT = "service_name"
)

// Provider returns a *schema.Provider for OVH.
func Provider() *schema.Provider {
return &schema.Provider{
Expand Down Expand Up @@ -154,6 +159,7 @@ func Provider() *schema.Provider {
"ovh_cloud_project_user": resourceCloudProjectUser(),
"ovh_cloud_project_user_s3_credential": resourceCloudProjectUserS3Credential(),
"ovh_cloud_project_user_s3_policy": resourceCloudProjectUserS3Policy(),
"ovh_cloud_project_workflow_backup": resourceCloudProjectWorkflowBackup(),
"ovh_dbaas_logs_input": resourceDbaasLogsInput(),
"ovh_dbaas_logs_output_graylog_stream": resourceDbaasLogsOutputGraylogStream(),
"ovh_dedicated_ceph_acl": resourceDedicatedCephACL(),
Expand Down
5 changes: 5 additions & 0 deletions ovh/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,8 @@ func testAccPreCheckDedicatedCeph(t *testing.T) {
testAccPreCheckCredentials(t)
checkEnvOrSkip(t, "OVH_DEDICATED_CEPH")
}

func testAccPreCheckWorkflowBackup(t *testing.T) {
checkEnvOrSkip(t, WORKFLOW_BACKUP_TEST_INSTANCE_ID_ENV_VAR)
checkEnvOrSkip(t, WORKFLOW_BACKUP_TEST_REGION_ENV_VAR)
}
148 changes: 148 additions & 0 deletions ovh/resource_cloud_project_workflow_backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package ovh

import (
"fmt"
"log"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/ovh/terraform-provider-ovh/ovh/helpers"
)

const (
OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_ENDPOINT = "/cloud/project/%s/region/%s/workflow/backup"
OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_REGION = "region_name"
OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_SERVICE = "service_name"
)

func resourceCloudProjectWorkflowBackup() *schema.Resource {
return &schema.Resource{
Create: resourceCloudProjectWorkflowBackupCreate,
Read: resourceCloudProjectWorkflowBackupRead,
Delete: resourceCloudProjectWorkflowBackupDelete,

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

Schema: resourceCloudProjectWorkflowBackupSchema(),
}
}

// No endpoint to update the workflow hence all attributes are ForceNew : true
func resourceCloudProjectWorkflowBackupSchema() map[string]*schema.Schema {
schema := map[string]*schema.Schema{
OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_SERVICE: {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DefaultFunc: schema.EnvDefaultFunc("OVH_CLOUD_PROJECT_SERVICE", nil),
},
OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_REGION: {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Region name.",
},
"cron": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"instance_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"max_execution_count": {
Type: schema.TypeInt,
Optional: true,
Computed: false,
ForceNew: true,
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"rotation": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},

"backup_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
// computed
"id": {
Type: schema.TypeString,
Computed: true,
},
"created_at": {
Type: schema.TypeString,
Computed: true,
},
}
return schema
}

func resourceCloudProjectWorkflowBackupCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
serviceName := d.Get(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_SERVICE).(string)
regionName := d.Get(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_REGION).(string)
endpoint := fmt.Sprintf(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_ENDPOINT, serviceName, regionName)
params := (&CloudProjectWorkflowBackupCreateOpts{}).FromResource(d)
res := &CloudProjectWorkflowBackupResponse{}

log.Printf("[DEBUG] will create workflow on %s", endpoint)
err := config.OVHClient.Post(endpoint, params, res)
if err != nil {
return fmt.Errorf("calling Post %s with param %+v:\n\t %w", endpoint, params, err)
}
d.SetId(res.Id)
return resourceCloudProjectWorkflowBackupRead(d, meta)
}

func resourceCloudProjectWorkflowBackupRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
serviceName := d.Get(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_SERVICE).(string)
regionName := d.Get(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_REGION).(string)
endpoint := fmt.Sprintf(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_ENDPOINT, serviceName, regionName) + "/" + d.Id()
res := &CloudProjectWorkflowBackupResponse{}

log.Printf("[DEBUG] Will read workflow backup on %s", endpoint)
if err := config.OVHClient.Get(endpoint, res); err != nil {
return helpers.CheckDeleted(d, err, endpoint)
}
log.Printf("[DEBUG] Response %s", res.ToMap())

for k, v := range res.ToMap() {
if k != "id" {
d.Set(k, fmt.Sprint(v))
} else {
d.SetId(fmt.Sprint(v))
}
}

log.Printf("[DEBUG] read %+v", res)
return nil
}

func resourceCloudProjectWorkflowBackupDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
serviceName := d.Get(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_SERVICE).(string)
regionName := d.Get(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_REGION).(string)
endpoint := fmt.Sprintf(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_ENDPOINT, serviceName, regionName) + "/" + d.Id()
log.Printf("[DEBUG] Will delete workflow backup on %s", endpoint)
err := config.OVHClient.Delete(endpoint, nil)
if err != nil {
return helpers.CheckDeleted(d, err, endpoint)
}
return nil
}
121 changes: 121 additions & 0 deletions ovh/resource_cloud_project_workflow_backup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package ovh

import (
"fmt"
"log"
"os"
"testing"

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

const WORKFLOW_BACKUP_TEST_CONF = `
resource "ovh_cloud_project_workflow_backup" "my_backup"{
service_name = "%s"
region_name = "%s"
cron = "50 4 * * *"
instance_id = "%s"
max_execution_count = "0"
name = "%s"
rotation = "7"
}
`
const WORKFLOW_BACKUP_TEST_CONF_UPDATED = `
resource "ovh_cloud_project_workflow_backup" "my_backup"{
service_name = "%s"
region_name = "%s"
cron = "50 4 * * *"
instance_id = "%s"
max_execution_count = "0"
name = "%s"
rotation = "5"
}
`

const CLOUD_PROJECT_TEST_ENV_VAR = "OVH_CLOUD_PROJECT_SERVICE_TEST"
const WORKFLOW_BACKUP_TEST_REGION_ENV_VAR = "OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_REGION_TEST"
const WORKFLOW_BACKUP_TEST_INSTANCE_ID_ENV_VAR = "OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_INSTANCE_ID_TEST"
const WORKFLOW_BACKUP_RESOURCE = "ovh_cloud_project_workflow_backup"
const WORKFLOW_BACKUP_RESOURCE_NAME = "ovh_cloud_project_workflow_backup.my_backup"

func init() {
resource.AddTestSweepers(WORKFLOW_BACKUP_RESOURCE, &resource.Sweeper{
Name: WORKFLOW_BACKUP_RESOURCE,
F: testSweepCloudProjectWorkflowBackup,
})
}

func testSweepCloudProjectWorkflowBackup(region string) error {
client, err := sharedClientForRegion(region)
if err != nil {
return fmt.Errorf("error getting client: %s", err)
}

region = os.Getenv(WORKFLOW_BACKUP_TEST_REGION_ENV_VAR)
if region == "" {
log.Printf("[DEBUG] No region in env variable => no sweeping")
return nil
}
wfToSweep := make([]CloudProjectWorkflowBackupResponse, 0)
var endpoint = fmt.Sprintf(OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_ENDPOINT, os.Getenv(CLOUD_PROJECT_TEST_ENV_VAR),
region)

if err := client.Get(endpoint, &wfToSweep); err != nil {
return fmt.Errorf("Error calling GET %s:\n\t %q", endpoint, err)
}

for _, wf := range wfToSweep {
var deleteEndpoint = endpoint + "/%s"
client.Delete(fmt.Sprintf(deleteEndpoint, wf.Id), nil)
if err != nil {
return fmt.Errorf("Error while deleting workflow with id %s through endpoint %s", wf.Id, deleteEndpoint)
}
log.Printf("[DEBUG] workflow %s is deleted", wf.Id)
}
return nil
}

func TestAccCloudProjectWorkflowBackup(t *testing.T) {
name := acctest.RandomWithPrefix(test_prefix)
var serviceName = os.Getenv(CLOUD_PROJECT_TEST_ENV_VAR)
var instanceId = os.Getenv(WORKFLOW_BACKUP_TEST_INSTANCE_ID_ENV_VAR)
var config = fmt.Sprintf(WORKFLOW_BACKUP_TEST_CONF,
serviceName,
os.Getenv(WORKFLOW_BACKUP_TEST_REGION_ENV_VAR),
instanceId,
name,
)

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheckCloud(t)
testAccCheckCloudProjectExists(t)
testAccPreCheckWorkflowBackup(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(WORKFLOW_BACKUP_RESOURCE_NAME, OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_SERVICE, serviceName),
resource.TestCheckResourceAttr(WORKFLOW_BACKUP_RESOURCE_NAME, "name", name),
resource.TestCheckResourceAttr(WORKFLOW_BACKUP_RESOURCE_NAME, "instance_id", instanceId),
),
},
{
Config: fmt.Sprintf(WORKFLOW_BACKUP_TEST_CONF_UPDATED,
serviceName,
os.Getenv(WORKFLOW_BACKUP_TEST_REGION_ENV_VAR),
instanceId,
name,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(WORKFLOW_BACKUP_RESOURCE_NAME, OVH_CLOUD_PROJECT_WORKFLOW_BACKUP_SERVICE, serviceName),
resource.TestCheckResourceAttr(WORKFLOW_BACKUP_RESOURCE_NAME, "name", name),
resource.TestCheckResourceAttr(WORKFLOW_BACKUP_RESOURCE_NAME, "instance_id", instanceId),
),
},
},
})
}
5 changes: 2 additions & 3 deletions ovh/resource_hosting_privatedatabase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@ resource "ovh_hosting_privatedatabase" "database" {

func init() {
resource.AddTestSweepers("ovh_hosting_privatedatabase", &resource.Sweeper{
Name: "ovh_hosting_privatedatabase",
Dependencies: []string{"ovh_hosting_privatedatabase"},
F: testSweepHostingPrivateDatabase,
Name: "ovh_hosting_privatedatabase",
F: testSweepHostingPrivateDatabase,
})
}

Expand Down
10 changes: 9 additions & 1 deletion ovh/resource_vrack_ip_loadbalancing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ovh

import (
"fmt"
"log"
"net/url"
"os"
"testing"
Expand Down Expand Up @@ -37,8 +38,15 @@ func testSweepVrackIpLoadbalancing(region string) error {
}

serviceName := os.Getenv("OVH_VRACK_SERVICE_TEST")
if serviceName == "" {
log.Print("[DEBUG] OVH_VRACK_SERVICE_TEST is not set. Unable to sweep VrackIpLoadbalancing")
return nil
}
ipLoadbalancing := os.Getenv("OVH_IPLB_SERVICE_TEST")

if ipLoadbalancing == "" {
log.Print("[DEBUG] OVH_IPLB_SERVICE_TEST is not set. Unable to sweep VrackIpLoadbalancing")
return nil
}
endpoint := fmt.Sprintf("/vrack/%s/ipLoadbalancing/%s",
url.PathEscape(serviceName),
url.PathEscape(ipLoadbalancing),
Expand Down
43 changes: 43 additions & 0 deletions ovh/types_cloud_project_workflow_backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package ovh

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

type CloudProjectWorkflowBackupCreateOpts struct {
Cron *string `json:"cron"`
InstanceId *string `json:"instanceId"`
MaxExecutionCount *int64 `json:"maxExecutionCount,omitempty"`
Name *string `json:"name"`
Rotation *int64 `json:"rotation"`
}

type CloudProjectWorkflowBackupResponse struct {
BackupName string `json:"backupName"`
CreatedAt string `json:"createdAt"`
Cron string `json:"cron"`
Id string `json:"id"`
InstanceId string `json:"instanceId"`
Name string `json:"name"`
}

func (opts *CloudProjectWorkflowBackupCreateOpts) FromResource(d *schema.ResourceData) *CloudProjectWorkflowBackupCreateOpts {
opts.Cron = helpers.GetNilStringPointerFromData(d, "cron")
opts.InstanceId = helpers.GetNilStringPointerFromData(d, "instance_id")
opts.MaxExecutionCount = helpers.GetNilInt64PointerFromData(d, "max_execution_count")
opts.Name = helpers.GetNilStringPointerFromData(d, "name")
opts.Rotation = helpers.GetNilInt64PointerFromData(d, "rotation")
return opts
}

func (v CloudProjectWorkflowBackupResponse) ToMap() map[string]interface{} {
obj := make(map[string]interface{})
obj["backup_name"] = v.BackupName
obj["created_at"] = v.CreatedAt
obj["cron"] = v.Cron
obj["id"] = v.Id
obj["instance_id"] = v.InstanceId
obj["name"] = v.Name
return obj
}
Loading

0 comments on commit e3dab41

Please sign in to comment.