From 64970ad870ede2c49dbd67b421bdf603d355b155 Mon Sep 17 00:00:00 2001 From: Celine Martha Sari Date: Sat, 17 Aug 2024 22:03:42 +0700 Subject: [PATCH] add vm desired_status --- README.md | 5 ++- docs/index.md | 69 +++++++++++++++++++++++++++++++++++------ provider/resource_vm.go | 64 ++++++++++++++++++++++++++++++++------ 3 files changed, 117 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 08d665c..a65b94e 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,9 @@ resource "idcloudhost_vm" "myvm" { # (optional) assign to floating ip network. if not, vm doesnt have public ip float_ip_address = idcloudhost_float_ip.myfloatip.address + + # add plan will ignored. changing vcpu & ram require desired_status = "stopped" + desired_status = "stopped" # "stopped", "running" # (optional). if unset will use your user default location # this field overwrite "default_location" @@ -125,7 +128,7 @@ resource "idcloudhost_vm" "myvm" { ## Next Development - Resource LB Network(Load Balancer) -- Resource VM add desired_status +- ✅ Resource VM add desired_status (v1.2.0) - ✅ Specific resource location (v1.1.0) - ✅ Support terraform import (v1.1.0) - ✅ Docs (v1.0.6) diff --git a/docs/index.md b/docs/index.md index 6f27e43..1a77c45 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,52 +2,88 @@ This is my personal idcloudhost terraform provider. It allows managing resources within compute and storage resources. ## Example Usage - +### 1. Load providers ```hcl -# 1. Load providers terraform { required_providers { idcloudhost = { source = "rizalmf/idcloudhost" - version = "=1.0.0" + version = "~> 1.0.0" } } } +``` -# 2. Configure the idcloudhost provider +### 2. Configure the idcloudhost provider +```hcl provider "idcloudhost" { # you can obtain by create new access as API Token on idcloudhost dashboard apikey="XXXXXXXXXXXXXXXXX" + + ## optional. if unset will use your user default location + default_location="jkt01" # jkt01(SouthJKT-a), jkt02(NorthJKT-a), jkt03(WestJKT-a), sgp01(Singapore) } +``` -# 3. Create s3 bucket storage +### 3. Create s3 bucket storage +```hcl # changable field: +# id = STORAGE NAME # - billing_account_id resource "idcloudhost_s3" "mybucket" { name = "mybucket" billing_account_id = 000000 } +``` -# 4. Create a VPC network +### 4. Create a VPC network +```hcl # changable field: +# id = PRIVATE NETWORK UUID # - name resource "idcloudhost_private_network" "myprivatenetwork" { # network_uuid = name = "mynetwork" + + # (optional). if unset will use your user default location + # this field overwrite "default_location" + # you can not change location on update + location = "jkt01" # jkt01(SouthJKT-a), jkt02(NorthJKT-a), jkt03(WestJKT-a), sgp01(Singapore) + + lifecycle { + ignore_changes = [ location ] + } + } +``` -# 5. Create Floating IP +### 5. Create Floating IP +```hcl # changable field: +# id = FLOAT IP ADDRESS # - name # - billing_account_id resource "idcloudhost_float_ip" "myfloatip" { # address = name = "myfloatnetwork" billing_account_id = 000000 + + # (optional). if unset will use your user default location + # this field overwrite "default_location" + # you can not change location on update + location = "jkt01" # jkt01(SouthJKT-a), jkt02(NorthJKT-a), jkt03(WestJKT-a), sgp01(Singapore) + + lifecycle { + ignore_changes = [ location ] + } + } +``` -# 6. Create vm +### 6. Create vm +```hcl # changable field: +# id = VM UUID # - name # - ram # - vcpu @@ -59,9 +95,9 @@ resource "idcloudhost_vm" "myvm" { name = "myvm" billing_account_id = 000000 username = "myusername" - password = "mypassword" + password = "Mypassword1" os_name = "ubuntu" - os_version = "22.04" + os_version = "22.04-lts" vcpu = 2 ram = 2048 #mb disks = 20 #gb @@ -71,5 +107,18 @@ resource "idcloudhost_vm" "myvm" { # (optional) assign to floating ip network. if not, vm doesnt have public ip float_ip_address = idcloudhost_float_ip.myfloatip.address + + # add plan will ignored. changing vcpu & ram require desired_status = "stopped" + desired_status = "stopped" # "stopped", "running" + + # (optional). if unset will use your user default location + # this field overwrite "default_location" + # you can not change location on update + location = "jkt01" # jkt01(SouthJKT-a), jkt02(NorthJKT-a), jkt03(WestJKT-a), sgp01(Singapore) + + lifecycle { + ignore_changes = [ location, os_name, os_version, username, password, billing_account_id ] + } + } ``` \ No newline at end of file diff --git a/provider/resource_vm.go b/provider/resource_vm.go index da7c396..0cf55eb 100644 --- a/provider/resource_vm.go +++ b/provider/resource_vm.go @@ -378,19 +378,11 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D config := m.(*Config) apiKey := config.ApiKey baseUrl := config.BaseUrl - // path := "/v1/user-resource/vm" defaultLocation := config.DefaultLocation path := "/user-resource/vm" version := "/v1" fullUrl := baseUrl + version + path location := d.Get("location").(string) - if defaultLocation != "" { - fullUrl = baseUrl + version + "/" + defaultLocation + path - } - if location != "" { - fullUrl = baseUrl + version + "/" + location + path - } - // fullUrl := baseUrl + path uuid := d.Id() disks_uuid := d.Get("disks_uuid").(string) @@ -398,14 +390,66 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D ram := d.Get("ram").(int) vcpu := d.Get("vcpu").(int) disks := d.Get("disks").(int) - // desired_status := d.Get("desired_status").(string) - // float_ip_address := d.Get("float_ip_address").(string) + desired_status := d.Get("desired_status").(string) if d.HasChange("desired_status") { + unregisteredStatus := true + statusPath := "start" + if desired_status == "stopped" { + unregisteredStatus = false + statusPath = "stop" + } + + if desired_status == "running" { + unregisteredStatus = false + } + if desired_status != "" && unregisteredStatus { + return diag.FromErr(fmt.Errorf("unregistered desired_status")) + } + if !unregisteredStatus { + version = "/v1" + path = "/user-resource/vm/" + statusPath + fullUrl = baseUrl + version + path + if defaultLocation != "" { + fullUrl = baseUrl + version + "/" + defaultLocation + path + } + if location != "" { + fullUrl = baseUrl + version + "/" + location + path + } + client := &http.Client{} + form := url.Values{} + form.Add("uuid", uuid) + req, err := http.NewRequest("POST", fullUrl, strings.NewReader(form.Encode())) + if err != nil { + return diag.FromErr(err) + } + req.PostForm = form + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("apikey", apiKey) + resp, err := client.Do(req) + if err != nil { + return diag.FromErr(err) + } + + if resp.StatusCode > 299 || resp.StatusCode < 200 { + bodyBytes, _ := io.ReadAll(resp.Body) + return diag.FromErr(fmt.Errorf(string(bodyBytes))) + } + defer resp.Body.Close() + } } if d.HasChanges("name", "ram", "vcpu") { + path = "/user-resource/vm" + version = "/v1" + fullUrl = baseUrl + version + path + if defaultLocation != "" { + fullUrl = baseUrl + version + "/" + defaultLocation + path + } + if location != "" { + fullUrl = baseUrl + version + "/" + location + path + } client := &http.Client{} form := url.Values{} form.Add("uuid", uuid)