From 770c364315292317d783e554d3e3da0090f1f9c2 Mon Sep 17 00:00:00 2001 From: yann degat Date: Fri, 13 Dec 2019 16:19:01 +0000 Subject: [PATCH] feat/r/dedicated_server_install_task: new resource --- ovh/dedicated_server_task.go | 2 +- ovh/provider.go | 1 + ...ource_ovh_dedicated_server_install_task.go | 136 +++++++++++++- ..._ovh_dedicated_server_install_task_test.go | 170 ++++++++++++++++++ ovh/types_dedicated_server.go | 52 ++++++ ...edicated_server_install_task.html.markdown | 87 +++++++++ website/ovh.erb | 3 + 7 files changed, 441 insertions(+), 10 deletions(-) create mode 100644 ovh/resource_ovh_dedicated_server_install_task_test.go create mode 100644 website/docs/r/dedicated_server_install_task.html.markdown diff --git a/ovh/dedicated_server_task.go b/ovh/dedicated_server_task.go index 0c6ad2508..386c8962c 100644 --- a/ovh/dedicated_server_task.go +++ b/ovh/dedicated_server_task.go @@ -30,7 +30,7 @@ func waitForDedicatedServerTask(serviceName string, task *DedicatedServerTask, c Pending: []string{"init", "todo", "doing"}, Target: []string{"done"}, Refresh: refreshFunc, - Timeout: 10 * time.Minute, + Timeout: 45 * time.Minute, Delay: 10 * time.Second, MinTimeout: 3 * time.Second, } diff --git a/ovh/provider.go b/ovh/provider.go index be1afc638..735c1b86d 100644 --- a/ovh/provider.go +++ b/ovh/provider.go @@ -69,6 +69,7 @@ func Provider() terraform.ResourceProvider { "ovh_cloud_network_private_subnet": resourcePublicCloudPrivateNetworkSubnet(), "ovh_cloud_user": resourcePublicCloudUser(), "ovh_dedicated_server_update": resourceDedicatedServerUpdate(), + "ovh_dedicated_server_install_task": resourceDedicatedServerInstallTask(), "ovh_dedicated_server_reboot_task": resourceDedicatedServerRebootTask(), "ovh_domain_zone_record": resourceOvhDomainZoneRecord(), "ovh_domain_zone_redirection": resourceOvhDomainZoneRedirection(), diff --git a/ovh/resource_ovh_dedicated_server_install_task.go b/ovh/resource_ovh_dedicated_server_install_task.go index d0b83e9b7..40d1d0996 100644 --- a/ovh/resource_ovh_dedicated_server_install_task.go +++ b/ovh/resource_ovh_dedicated_server_install_task.go @@ -15,9 +15,14 @@ import ( func resourceDedicatedServerInstallTask() *schema.Resource { return &schema.Resource{ Create: resourceDedicatedServerInstallTaskCreate, + Update: resourceDedicatedServerInstallTaskUpdate, Read: resourceDedicatedServerInstallTaskRead, Delete: resourceDedicatedServerInstallTaskDelete, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(45 * time.Minute), + }, + Schema: map[string]*schema.Schema{ "service_name": { Type: schema.TypeString, @@ -25,13 +30,101 @@ func resourceDedicatedServerInstallTask() *schema.Resource { ForceNew: true, Description: "The internal name of your dedicated server.", }, - "keepers": { - Type: schema.TypeList, + "partition_scheme_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Partition scheme name.", + }, + "template_name": { + Type: schema.TypeString, Required: true, ForceNew: true, - Description: "Change this value to recreate an install task.", - Elem: &schema.Schema{ - Type: schema.TypeString, + Description: "Template name", + }, + "bootid_on_destroy": { + Type: schema.TypeInt, + Optional: true, + Description: "If set, reboot the server on the specified boot id during destroy phase", + }, + "details": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "change_log": { + Type: schema.TypeString, + Optional: true, + Description: "Template change log details", + }, + "custom_hostname": { + Type: schema.TypeString, + Optional: true, + Description: "Set up the server using the provided hostname instead of the default hostname", + }, + "disk_group_id": { + Type: schema.TypeInt, + Optional: true, + Description: "", + }, + "install_rtm": { + Type: schema.TypeBool, + Optional: true, + Description: "", + }, + "install_sql_server": { + Type: schema.TypeBool, + Optional: true, + Description: "", + }, + "language": { + Type: schema.TypeString, + Optional: true, + Description: "language", + }, + "no_raid": { + Type: schema.TypeBool, + Optional: true, + Description: "", + }, + "post_installation_script_link": { + Type: schema.TypeString, + Optional: true, + Description: "Indicate the URL where your postinstall customisation script is located", + }, + "post_installation_script_return": { + Type: schema.TypeString, + Optional: true, + Description: "indicate the string returned by your postinstall customisation script on successful execution. Advice: your script should return a unique validation string in case of succes. A good example is 'loh1Xee7eo OK OK OK UGh8Ang1Gu'", + }, + "reset_hw_raid": { + Type: schema.TypeBool, + Optional: true, + Description: "", + }, + "soft_raid_devices": { + Type: schema.TypeInt, + Optional: true, + Description: "", + }, + "ssh_key_name": { + Type: schema.TypeString, + Optional: true, + Description: "Name of the ssh key that should be installed. Password login will be disabled", + }, + "use_spla": { + Type: schema.TypeBool, + Optional: true, + Description: "", + }, + "use_distrib_kernel": { + Type: schema.TypeBool, + Optional: true, + Description: "Use the distribution's native kernel instead of the recommended OVH Kernel", + }, + }, }, }, @@ -75,13 +168,13 @@ func resourceDedicatedServerInstallTaskCreate(d *schema.ResourceData, meta inter serviceName := d.Get("service_name").(string) endpoint := fmt.Sprintf( - "/dedicated/server/%s/reboot", + "/dedicated/server/%s/install/start", url.PathEscape(serviceName), ) - + opts := (&DedicatedServerInstallTaskCreateOpts{}).FromResource(d) task := &DedicatedServerTask{} - if err := config.OVHClient.Post(endpoint, nil, task); err != nil { + if err := config.OVHClient.Post(endpoint, opts, task); err != nil { return fmt.Errorf("Error calling POST %s:\n\t %q", endpoint, err) } @@ -101,7 +194,7 @@ func resourceDedicatedServerInstallTaskRead(d *schema.ResourceData, meta interfa id, err := strconv.ParseInt(d.Id(), 10, 64) if err != nil { return fmt.Errorf( - "Could not parse reboot task id %s,%s:\n\t %q", + "Could not parse install task id %s,%s:\n\t %q", serviceName, d.Id(), err, @@ -131,7 +224,32 @@ func resourceDedicatedServerInstallTaskRead(d *schema.ResourceData, meta interfa return nil } +func resourceDedicatedServerInstallTaskUpdate(d *schema.ResourceData, meta interface{}) error { + // nothing to do on update + return resourceDedicatedServerInstallTaskRead(d, meta) +} + func resourceDedicatedServerInstallTaskDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + bootId := getNilIntPointerFromData(d, "bootid_on_destroy") + + if bootId != nil { + serviceName := d.Get("service_name").(string) + endpoint := fmt.Sprintf( + "/dedicated/server/%s/reboot", + url.PathEscape(serviceName), + ) + + task := &DedicatedServerTask{} + if err := config.OVHClient.Post(endpoint, nil, task); err != nil { + return fmt.Errorf("Error calling POST %s:\n\t %q", endpoint, err) + } + + if err := waitForDedicatedServerTask(serviceName, task, config.OVHClient); err != nil { + return err + } + } + // we cant delete the task through the API, just forget about its Id d.SetId("") return nil diff --git a/ovh/resource_ovh_dedicated_server_install_task_test.go b/ovh/resource_ovh_dedicated_server_install_task_test.go new file mode 100644 index 000000000..67250f60a --- /dev/null +++ b/ovh/resource_ovh_dedicated_server_install_task_test.go @@ -0,0 +1,170 @@ +package ovh + +import ( + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccDedicatedServerInstall_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckCredentials(t) + testAccPreCheckDedicatedServer(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDedicatedServerInstallConfig("basic"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "ovh_dedicated_server_update.server", "state", "ok"), + resource.TestCheckResourceAttr( + "ovh_dedicated_server_update.server", "monitoring", "true"), + resource.TestCheckResourceAttr( + "ovh_dedicated_server_update.server", "state", "ok"), + resource.TestCheckResourceAttr( + "ovh_dedicated_server_install_task.server_install", "function", "reinstallServer"), + resource.TestCheckResourceAttr( + "ovh_dedicated_server_install_task.server_install", "status", "done"), + ), + }, + }, + }) +} + +func TestAccDedicatedServerInstall_rebootondestroy(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckCredentials(t) + testAccPreCheckDedicatedServer(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDedicatedServerInstallConfig("rebootondestroy"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "ovh_dedicated_server_update.server", "state", "ok"), + resource.TestCheckResourceAttr( + "ovh_dedicated_server_update.server", "monitoring", "true"), + resource.TestCheckResourceAttr( + "ovh_dedicated_server_update.server", "state", "ok"), + resource.TestCheckResourceAttr( + "ovh_dedicated_server_install_task.server_install", "function", "reinstallServer"), + resource.TestCheckResourceAttr( + "ovh_dedicated_server_install_task.server_install", "status", "done"), + ), + }, + }, + }) +} + +func testAccDedicatedServerInstallConfig(config string) string { + dedicated_server := os.Getenv("OVH_DEDICATED_SERVER") + testName := acctest.RandomWithPrefix(test_prefix) + sshKey := os.Getenv("OVH_SSH_KEY") + if sshKey == "" { + sshKey = "ssh-ed25519 AAAAC3NzaC1yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + } + + if config == "rebootondestroy" { + return fmt.Sprintf( + testAccDedicatedServerInstallConfig_RebootOnDestroy, + dedicated_server, + testName, + sshKey, + testName, + ) + } + + return fmt.Sprintf( + testAccDedicatedServerInstallConfig_Basic, + dedicated_server, + testName, + sshKey, + testName, + ) + +} + +const testAccDedicatedServerInstallConfig_Basic = ` +data ovh_dedicated_server_boots "harddisk" { + service_name = "%s" + boot_type = "harddisk" +} + +resource "ovh_me_ssh_key" "key" { + key_name = "%s" + key = "%s" +} + +resource ovh_dedicated_server_update "server" { + service_name = data.ovh_dedicated_server_boots.harddisk.service_name + boot_id = data.ovh_dedicated_server_boots.harddisk.result[0] + monitoring = true + state = "ok" +} + +resource "ovh_me_installation_template" "debian" { + base_template_name = "debian10_64" + template_name = "%s" + default_language = "en" + + customization { + change_log = "v1" + custom_hostname = "mytest" + ssh_key_name = ovh_me_ssh_key.key.key_name + } +} + +resource ovh_dedicated_server_install_task "server_install" { + service_name = data.ovh_dedicated_server_boots.harddisk.service_name + template_name = ovh_me_installation_template.debian.template_name +} +` + +const testAccDedicatedServerInstallConfig_RebootOnDestroy = ` +data ovh_dedicated_server_boots "harddisk" { + service_name = "%s" + boot_type = "harddisk" +} + +data ovh_dedicated_server_boots "rescue" { + service_name = data.ovh_dedicated_server_boots.harddisk.service_name + boot_type = "rescue" +} + +resource "ovh_me_ssh_key" "key" { + key_name = "%s" + key = "%s" +} + +resource ovh_dedicated_server_update "server" { + service_name = data.ovh_dedicated_server_boots.harddisk.service_name + boot_id = data.ovh_dedicated_server_boots.harddisk.result[0] + monitoring = true + state = "ok" +} + +resource "ovh_me_installation_template" "debian" { + base_template_name = "debian10_64" + template_name = "%s" + default_language = "en" + + customization { + change_log = "v1" + custom_hostname = "mytest" + ssh_key_name = ovh_me_ssh_key.key.key_name + } +} + +resource ovh_dedicated_server_install_task "server_install" { + service_name = data.ovh_dedicated_server_boots.harddisk.service_name + template_name = ovh_me_installation_template.debian.template_name + bootid_on_destroy = data.ovh_dedicated_server_boots.rescue.result[0] +} +` diff --git a/ovh/types_dedicated_server.go b/ovh/types_dedicated_server.go index 0dddb0413..16a26bd41 100644 --- a/ovh/types_dedicated_server.go +++ b/ovh/types_dedicated_server.go @@ -101,3 +101,55 @@ type DedicatedServerTask struct { DoneDate time.Time `json:"doneDate"` StartDate time.Time `json:"startDate"` } + +type DedicatedServerInstallTaskCreateOpts struct { + TemplateName string `json:"templateName"` + PartitionSchemeName *string `json:"partitionSchemeName,omitempty"` + Details *DedicatedServerInstallTaskDetails `json:"details"` +} + +func (opts *DedicatedServerInstallTaskCreateOpts) FromResource(d *schema.ResourceData) *DedicatedServerInstallTaskCreateOpts { + opts.TemplateName = d.Get("template_name").(string) + opts.PartitionSchemeName = getNilStringPointerFromData(d, "partition_scheme_name") + + details := d.Get("details").([]interface{}) + if details != nil && len(details) == 1 { + opts.Details = (&DedicatedServerInstallTaskDetails{}).FromResource(d, "details.0") + + } + return opts +} + +type DedicatedServerInstallTaskDetails struct { + CustomHostname *string `json:"customHostname,omitempty"` + DiskGroupId *int64 `json:"diskGroupId,omitempty"` + InstallRTM *bool `json:"installRTM,omitempty"` + InstallSqlServer *bool `json:"installSqlServer,omitempty"` + Language *string `json:"language,omitempty"` + NoRaid *bool `json:"noRaid,omitempty"` + PostInstallationScriptLink *string `json:"postInstallationScriptLink,omitempty"` + PostInstallationScriptReturn *string `json:"postInstallationScriptReturn,omitempty"` + ResetHwRaid *bool `json:"resetHwRaid,omitempty"` + SoftRaidDevices *int64 `json:"softRaidDevices,omitempty"` + SshKeyName *string `json:"sshKeyName,omitempty"` + UseDistribKernel *bool `json:"useDistribKernel,omitempty"` + UseSpla *bool `json:"useSpla,omitempty"` +} + +func (opts *DedicatedServerInstallTaskDetails) FromResource(d *schema.ResourceData, parent string) *DedicatedServerInstallTaskDetails { + opts.CustomHostname = getNilStringPointerFromData(d, fmt.Sprintf("%s.custom_hostname", parent)) + opts.DiskGroupId = getNilInt64PointerFromData(d, fmt.Sprintf("%s.disk_group_id", parent)) + opts.InstallRTM = getNilBoolPointerFromData(d, fmt.Sprintf("%s.install_rtm", parent)) + opts.InstallSqlServer = getNilBoolPointerFromData(d, fmt.Sprintf("%s.install_sql_server", parent)) + opts.Language = getNilStringPointerFromData(d, fmt.Sprintf("%s.language", parent)) + opts.NoRaid = getNilBoolPointerFromData(d, fmt.Sprintf("%s.no_raid", parent)) + opts.PostInstallationScriptLink = getNilStringPointerFromData(d, fmt.Sprintf("%s.post_installation_script_link", parent)) + opts.PostInstallationScriptReturn = getNilStringPointerFromData(d, fmt.Sprintf("%s.post_installation_script_return", parent)) + opts.ResetHwRaid = getNilBoolPointerFromData(d, fmt.Sprintf("%s.reset_hw_raid", parent)) + opts.SoftRaidDevices = getNilInt64PointerFromData(d, fmt.Sprintf("%s.soft_raid_devices", parent)) + opts.SshKeyName = getNilStringPointerFromData(d, fmt.Sprintf("%s.ssh_key_name", parent)) + opts.UseDistribKernel = getNilBoolPointerFromData(d, fmt.Sprintf("%s.use_distrib_kernel", parent)) + opts.UseSpla = getNilBoolPointerFromData(d, fmt.Sprintf("%s.use_spla", parent)) + + return opts +} diff --git a/website/docs/r/dedicated_server_install_task.html.markdown b/website/docs/r/dedicated_server_install_task.html.markdown new file mode 100644 index 000000000..8774495f3 --- /dev/null +++ b/website/docs/r/dedicated_server_install_task.html.markdown @@ -0,0 +1,87 @@ +--- +layout: "ovh" +page_title: "OVH: dedicated_server_install_task" +sidebar_current: "docs-ovh-resource-dedicated-server-install-task" +description: |- + Install your Dedicated Server +--- + +# ovh_dedicated_server_install_task + +Install your Dedicated Server. + +> NOTE: After some delay, if the task is marked as `done`, the Provider +may purge it. To avoid raising errors when terraform refreshes its plan, +404 errors are ignored on Resource Read, thus some information may be lost +after a while. + +## Example Usage + +```hcl +data ovh_dedicated_server_boots "rescue" { + service_name = "ns00000.ip-1-2-3.eu" + boot_type = "rescue" +} + +resource "ovh_me_ssh_key" "key" { + key_name = "mykey" + key = "ssh-ed25519 AAAAC3..." +} + +resource "ovh_me_installation_template" "debian" { + base_template_name = "debian10_64" + template_name = "mydebian10" + default_language = "en" + + customization { + change_log = "v1" + custom_hostname = "mytest" + ssh_key_name = ovh_me_ssh_key.key.key_name + } +} + +resource ovh_dedicated_server_install_task "server_install" { + service_name = "ns00000.ip-1-2-3.eu" + template_name = ovh_me_installation_template.debian.template_name + bootid_on_destroy = data.ovh_dedicated_server_boots.rescue.result[0] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `service_name` - (Required) The service_name of your dedicated server. +* `partition_scheme_name` - Partition scheme name. +* `template_name` - (Required) Template name. +* `bootid_on_destroy` - If set, reboot the server on the specified boot id during destroy phase. +* `details` - see `details` block below. + +The `details` block supports: + +* `change_log` - Template change log details. +* `custom_hostname` - Set up the server using the provided hostname instead of the default hostname. +* `disk_group_id` - Disk group id. +* `install_rtm` - set to true to install RTM. +* `install_sql_server` - set to true to install sql server (Windows template only). +* `language` - language. +* `no_raid` - set to true to disable RAID. +* `post_installation_script_link` - Indicate the URL where your postinstall customisation script is located. +* `post_installation_script_return` - Indicate the string returned by your postinstall customisation script on successful execution. Advice: your script should return a unique validation string in case of succes. A good example is 'loh1Xee7eo OK OK OK UGh8Ang1Gu'. +* `reset_hw_raid` - set to true to make a hardware raid reset. +* `soft_raid_devices` - soft raid devices. +* `ssh_key_name` - Name of the ssh key that should be installed. Password login will be disabled. +* `use_spla` - set to true to use SPLA. +* `use_distrib_kernel` - Use the distribution's native kernel instead of the recommended OVH Kernel. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The task id +* `comment` - Details of this task. (should be `Install asked`) +* `done_date` - Completion date in RFC3339 format. +* `function` - Function name (should be `hardInstall`). +* `last_update` - Last update in RFC3339 format. +* `start_date` - Task creation date in RFC3339 format. +* `status` - Task status (should be `done`) diff --git a/website/ovh.erb b/website/ovh.erb index 008908da0..c8ef9cb38 100644 --- a/website/ovh.erb +++ b/website/ovh.erb @@ -101,6 +101,9 @@ > Dedicated Server