From e4dc0112de942799017543ed23872363bf73a39e Mon Sep 17 00:00:00 2001 From: Alejandro JNM Date: Wed, 15 Apr 2020 17:42:00 -0400 Subject: [PATCH] feat: Added the option to import existing infrastructure - Update all comment in all components - Added the option to import existing infrastructure - Update civogo lib to 0.2.5 BREAKING CHANGE: No Signed-off-by: Alejandro JNM --- civo/datasource_common_schema.go | 1 + civo/datasource_common_struct.go | 1 + civo/datasource_intances_size.go | 9 ++- civo/datasource_kubernetes_version.go | 10 +++- civo/datasource_template.go | 4 ++ civo/provider.go | 2 + civo/resource_dns_domain_name.go | 42 ++++++++++++-- civo/resource_dns_domain_record.go | 80 +++++++++++++++++++++------ civo/resource_firewall.go | 18 ++++-- civo/resource_firewall_rule.go | 53 +++++++++++++++--- civo/resource_instance.go | 59 ++++++++++++-------- civo/resource_kubernetes_cluster.go | 38 +++++++++---- civo/resource_loadbalance.go | 27 ++++++--- civo/resource_network.go | 27 +++++---- civo/resource_snapshot.go | 25 ++++++--- civo/resource_ssh.go | 18 ++++-- civo/resource_template.go | 50 ++++++++++++++--- civo/resource_volume.go | 58 +++++++++---------- civo/utils.go | 12 ++++ go.mod | 2 +- go.sum | 2 + 21 files changed, 399 insertions(+), 139 deletions(-) diff --git a/civo/datasource_common_schema.go b/civo/datasource_common_schema.go index b1631408..cef61133 100644 --- a/civo/datasource_common_schema.go +++ b/civo/datasource_common_schema.go @@ -4,6 +4,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) +// Function to define a custom schema filter for data source func dataSourceFiltersSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeSet, diff --git a/civo/datasource_common_struct.go b/civo/datasource_common_struct.go index 9036b4f0..03bb496e 100644 --- a/civo/datasource_common_struct.go +++ b/civo/datasource_common_struct.go @@ -1,5 +1,6 @@ package civo +// Customs struct for Filter used in dataSourceFiltersSchema type Filter struct { Name string Values []string diff --git a/civo/datasource_intances_size.go b/civo/datasource_intances_size.go index bc3727e3..16bca4c4 100644 --- a/civo/datasource_intances_size.go +++ b/civo/datasource_intances_size.go @@ -4,10 +4,13 @@ import ( "fmt" "github.com/civo/civogo" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "log" "regexp" "strconv" ) +// Data source to get and filter all instances size +// use to define the size in resourceInstance func dataSourceInstancesSize() *schema.Resource { return &schema.Resource{ Read: dataSourceInstancesSizeRead, @@ -56,11 +59,13 @@ func dataSourceInstancesSizeRead(d *schema.ResourceData, m interface{}) error { } if filtersOk { + log.Printf("[INFO] Getting the instances size") resp, err := apiClient.ListInstanceSizes() if err != nil { return fmt.Errorf("no instances size was found in the server") } + log.Printf("[INFO] Finding the size of the instances") size, err := findInstancesSizeByFilter(resp, filters.(*schema.Set)) if err != nil { return fmt.Errorf("no instances size was found in the server, %s", err) @@ -159,7 +164,7 @@ func findInstancesSizeByFilter(sizes []civogo.InstanceSize, set *schema.Set) (*c return &results[0], nil } if len(results) == 0 { - return nil, fmt.Errorf("no sizes found for your search") + return nil, fmt.Errorf("no instances sizes found for your search") } - return nil, fmt.Errorf("too many sizes found (found %d, expected 1)", len(results)) + return nil, fmt.Errorf("too many instances sizes found (found %d, expected 1)", len(results)) } diff --git a/civo/datasource_kubernetes_version.go b/civo/datasource_kubernetes_version.go index 9ce5d95e..fd75f142 100644 --- a/civo/datasource_kubernetes_version.go +++ b/civo/datasource_kubernetes_version.go @@ -4,8 +4,12 @@ import ( "fmt" "github.com/civo/civogo" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "log" ) +// Data source to get and filter all kubernetes version +// available in the server, use to define the version at the +// moment of the cluster creation in resourceKubernetesCluster func dataSourceKubernetesVersion() *schema.Resource { return &schema.Resource{ Read: dataSourceKubernetesVersionRead, @@ -42,11 +46,13 @@ func dataSourceKubernetesVersionRead(d *schema.ResourceData, m interface{}) erro } if filtersOk { + log.Printf("[INFO] Getting all versions of kubernetes") resp, err := apiClient.ListAvailableKubernetesVersions() if err != nil { return fmt.Errorf("no version was found in the server") } + log.Printf("[INFO] Finding the version of kubernetes") version, err := findKubernetesVersionByFilter(resp, filters.(*schema.Set)) if err != nil { return fmt.Errorf("no version was found in the server, %s", err) @@ -99,7 +105,7 @@ func findKubernetesVersionByFilter(version []civogo.KubernetesVersion, set *sche return &results[0], nil } if len(results) == 0 { - return nil, fmt.Errorf("no version found for your search") + return nil, fmt.Errorf("no kubernetes version found for your search") } - return nil, fmt.Errorf("too many version found (found %d, expected 1)", len(results)) + return nil, fmt.Errorf("too many kubernetes version found (found %d, expected 1)", len(results)) } diff --git a/civo/datasource_template.go b/civo/datasource_template.go index cddeb1ab..fca43445 100644 --- a/civo/datasource_template.go +++ b/civo/datasource_template.go @@ -5,8 +5,11 @@ import ( "github.com/civo/civogo" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "log" ) +// Data source to get from the api a specific template +// using the code of the image func dataSourceTemplate() *schema.Resource { return &schema.Resource{ Read: dataSourceTemplateRead, @@ -68,6 +71,7 @@ func dataSourceTemplateRead(d *schema.ResourceData, m interface{}) error { } if hasCode { + log.Printf("[INFO] Getting all template") image, err := apiClient.GetTemplateByCode(code.(string)) if err != nil { fmt.Errorf("[ERR] failed to retrive template: %s", err) diff --git a/civo/provider.go b/civo/provider.go index 4fcb24d7..5dc6f3b8 100644 --- a/civo/provider.go +++ b/civo/provider.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/terraform" ) +// Civo cloud provider func Provider() terraform.ResourceProvider { return &schema.Provider{ Schema: map[string]*schema.Schema{ @@ -38,6 +39,7 @@ func Provider() terraform.ResourceProvider { } } +// Provider configuration func providerConfigure(d *schema.ResourceData) (interface{}, error) { token := d.Get("token").(string) client, _ := civogo.NewClient(token) diff --git a/civo/resource_dns_domain_name.go b/civo/resource_dns_domain_name.go index 807b671e..a2c003d4 100644 --- a/civo/resource_dns_domain_name.go +++ b/civo/resource_dns_domain_name.go @@ -7,6 +7,7 @@ import ( "log" ) +// Dns Domain resource, with this we can create and manage DNS Domain func resourceDnsDomainName() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -29,14 +30,16 @@ func resourceDnsDomainName() *schema.Resource { Delete: resourceDnsDomainNameDelete, //Exists: resourceExistsItem, Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + State: resourceDnsDomainImport, }, } } +// function to create a new domain in your account func resourceDnsDomainNameCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] Creating the domain %s", d.Get("name").(string)) dnsDomain, err := apiClient.CreateDNSDomain(d.Get("name").(string)) if err != nil { fmt.Errorf("failed to create a new domains: %s", err) @@ -48,9 +51,11 @@ func resourceDnsDomainNameCreate(d *schema.ResourceData, m interface{}) error { return resourceDnsDomainNameRead(d, m) } +// function to read a domain from your account func resourceDnsDomainNameRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retriving the domain %s", d.Get("name").(string)) resp, err := apiClient.GetDNSDomain(d.Get("name").(string)) if err != nil { if resp != nil { @@ -58,7 +63,7 @@ func resourceDnsDomainNameRead(d *schema.ResourceData, m interface{}) error { return nil } - return fmt.Errorf("error retrieving domain: %s", err) + return fmt.Errorf("[ERR] error retrieving domain: %s", err) } d.Set("name", resp.Name) @@ -67,21 +72,24 @@ func resourceDnsDomainNameRead(d *schema.ResourceData, m interface{}) error { return nil } +// function to update a specific domain func resourceDnsDomainNameUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] Searching the domain %s", d.Get("name").(string)) resp, err := apiClient.FindDNSDomain(d.Id()) if err != nil { - log.Printf("[WARN] Civo domain (%s) not found", d.Id()) + log.Printf("[WARN] domain (%s) not found", d.Id()) d.SetId("") return nil } if d.HasChange("name") { name := d.Get("name").(string) + log.Printf("[INFO] Renaming the domain to %s", d.Get("name").(string)) _, err := apiClient.UpdateDNSDomain(resp, name) if err != nil { - log.Printf("[WARN] An error occurred while renamed the domain (%s)", d.Id()) + return fmt.Errorf("[WARN] an error occurred while renamed the domain (%s)", d.Id()) } } @@ -89,19 +97,41 @@ func resourceDnsDomainNameUpdate(d *schema.ResourceData, m interface{}) error { return resourceDnsDomainNameRead(d, m) } +// function to delete a specific domain func resourceDnsDomainNameDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] Searching the domain to %s", d.Get("name").(string)) resp, err := apiClient.FindDNSDomain(d.Id()) if err != nil { - log.Printf("[WARN] Civo domain (%s) not found", d.Id()) + log.Printf("[WARN] domain (%s) not found", d.Id()) d.SetId("") return nil } + log.Printf("[INFO] Deleting the domain %s", d.Get("name").(string)) _, err = apiClient.DeleteDNSDomain(resp) if err != nil { - log.Printf("[INFO] Civo domain (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete the domain %s", d.Id()) } return nil } + +// custom import to able add a main domain to the terraform +func resourceDnsDomainImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + apiClient := m.(*civogo.Client) + + log.Printf("[INFO] Searching the domain %s", d.Get("name").(string)) + resp, err := apiClient.GetDNSDomain(d.Id()) + if err != nil { + if resp != nil { + return nil, err + } + } + + d.SetId(resp.ID) + d.Set("name", resp.Name) + d.Set("account_id", resp.AccountID) + + return []*schema.ResourceData{d}, nil +} diff --git a/civo/resource_dns_domain_record.go b/civo/resource_dns_domain_record.go index 863ed9e8..b4d98fce 100644 --- a/civo/resource_dns_domain_record.go +++ b/civo/resource_dns_domain_record.go @@ -8,6 +8,7 @@ import ( "log" ) +// Constant all possible DNS Record const ( // DNSRecordTypeA represents an A record DNSRecordTypeA = "a" @@ -22,6 +23,7 @@ const ( DNSRecordTypeTXT = "txt" ) +// Dns domain record resource with this we can create and manage DNS Domain func resourceDnsDomainRecord() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -35,6 +37,12 @@ func resourceDnsDomainRecord() *schema.Resource { Type: schema.TypeString, Required: true, Description: "The choice of RR type from a, cname, mx or txt", + ValidateFunc: validation.StringInSlice([]string{ + DNSRecordTypeA, + DNSRecordTypeCName, + DNSRecordTypeMX, + DNSRecordTypeTXT, + }, false), }, "name": { Type: schema.TypeString, @@ -79,14 +87,16 @@ func resourceDnsDomainRecord() *schema.Resource { Delete: resourceDnsDomainRecordDelete, //Exists: resourceExistsItem, Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + State: resourceDnsDomainRecordImport, }, } } +// function to create a new record for the main domain func resourceDnsDomainRecordCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] configuring the domain record %s", d.Get("name").(string)) config := &civogo.DNSRecordConfig{ Name: d.Get("name").(string), Value: d.Get("value").(string), @@ -116,9 +126,10 @@ func resourceDnsDomainRecordCreate(d *schema.ResourceData, m interface{}) error config.Type = DNSRecordTypeTXT } + log.Printf("[INFO] Creating the domain record %s", d.Get("name").(string)) dnsDomainRecord, err := apiClient.CreateDNSRecord(d.Get("domain_id").(string), config) if err != nil { - fmt.Errorf("failed to create a new record: %s", err) + fmt.Errorf("[ERR] failed to create a new domain record: %s", err) return err } @@ -127,14 +138,18 @@ func resourceDnsDomainRecordCreate(d *schema.ResourceData, m interface{}) error return resourceDnsDomainRecordRead(d, m) } +// function to read a dns domain record func resourceDnsDomainRecordRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retriving the domain record %s", d.Get("name").(string)) resp, err := apiClient.GetDNSRecord(d.Get("domain_id").(string), d.Id()) if err != nil { - log.Printf("[WARN] civo domain record (%s) not found", d.Id()) - d.SetId("") - return nil + if resp != nil { + d.SetId("") + return nil + } + return fmt.Errorf("[WARN] domain record (%s) not found", d.Id()) } d.Set("name", resp.Name) @@ -145,20 +160,19 @@ func resourceDnsDomainRecordRead(d *schema.ResourceData, m interface{}) error { d.Set("type", resp.Type) d.Set("priority", resp.Priority) d.Set("ttl", resp.TTL) - d.Set("created_at", resp.CreatedAt.String()) - d.Set("updated_at", resp.UpdatedAt.String()) + d.Set("created_at", resp.CreatedAt.UTC().String()) + d.Set("updated_at", resp.UpdatedAt.UTC().String()) return nil } +// function to update a dns domain record func resourceDnsDomainRecordUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) resp, err := apiClient.GetDNSRecord(d.Get("domain_id").(string), d.Id()) if err != nil { - log.Printf("[WARN] civo domain record (%s) not found", d.Id()) - d.SetId("") - return nil + return fmt.Errorf("[WARN] domain record (%s) not found", d.Id()) } config := &civogo.DNSRecordConfig{} @@ -186,30 +200,62 @@ func resourceDnsDomainRecordUpdate(d *schema.ResourceData, m interface{}) error } } + log.Printf("[INFO] Updating the domain record %s", d.Get("name").(string)) _, err = apiClient.UpdateDNSRecord(resp, config) if err != nil { - log.Printf("[WARN] an error occurred while renamed the domain record (%s)", d.Id()) + return fmt.Errorf("[ERR] an error occurred while renamed the domain record %s, %s", d.Id(), err) } return resourceDnsDomainRecordRead(d, m) } +//function to delete a dns domain record func resourceDnsDomainRecordDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] Searching the domain record %s", d.Get("name").(string)) resp, err := apiClient.GetDNSRecord(d.Get("domain_id").(string), d.Id()) if err != nil { - log.Printf("[WARN] civo domain record (%s) not found", d.Id()) - d.SetId("") - return nil + return fmt.Errorf("[WARN] domain record (%s) not found", d.Id()) } + log.Printf("[INFO] deleting the domain record %s", d.Get("name").(string)) _, err = apiClient.DeleteDNSRecord(resp) if err != nil { - log.Printf("[WARN] civo domain record (%s) not found", d.Id()) - d.SetId("") - return nil + return fmt.Errorf("[WARN] an error occurred while tring to delete the domain record %s", d.Id()) } return nil } + +// custom import to able to add a main domain to the terraform +func resourceDnsDomainRecordImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + apiClient := m.(*civogo.Client) + + domainId, DomainRecordId, err := resourceCommonParseId(d.Id()) + if err != nil { + return nil, err + } + + log.Printf("[INFO] retriving the domain record %s", DomainRecordId) + resp, err := apiClient.GetDNSRecord(domainId, DomainRecordId) + if err != nil { + if resp != nil { + return nil, err + } + } + + d.SetId(resp.ID) + d.Set("name", resp.Name) + d.Set("account_id", resp.AccountID) + d.Set("domain_id", resp.DNSDomainID) + d.Set("name", resp.Name) + d.Set("value", resp.Value) + d.Set("type", resp.Type) + d.Set("priority", resp.Priority) + d.Set("ttl", resp.TTL) + d.Set("created_at", resp.CreatedAt.UTC().String()) + d.Set("updated_at", resp.UpdatedAt.UTC().String()) + + return []*schema.ResourceData{d}, nil +} diff --git a/civo/resource_firewall.go b/civo/resource_firewall.go index 0d3921b7..9cbd6401 100644 --- a/civo/resource_firewall.go +++ b/civo/resource_firewall.go @@ -7,6 +7,7 @@ import ( "log" ) +// Firewall resource with this we can create and manage all firewall func resourceFirewall() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -31,12 +32,14 @@ func resourceFirewall() *schema.Resource { } } +// function to create a firewall func resourceFirewallCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] creating a new firewall %s", d.Get("name").(string)) firewall, err := apiClient.NewFirewall(d.Get("name").(string)) if err != nil { - fmt.Errorf("failed to create a new firewall: %s", err) + fmt.Errorf("[ERR] failed to create a new firewall: %s", err) return err } @@ -45,17 +48,18 @@ func resourceFirewallCreate(d *schema.ResourceData, m interface{}) error { return resourceFirewallRead(d, m) } +// function to read a firewall func resourceFirewallRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retriving the firewall %s", d.Id()) resp, err := apiClient.FindFirewall(d.Id()) if err != nil { if resp != nil { d.SetId("") return nil } - - return fmt.Errorf("[ERR] error retrieving firewall: %s", err) + return fmt.Errorf("[ERR] error retrieving firewall %s, %s", d.Id(), err) } d.Set("name", resp.Name) @@ -64,14 +68,16 @@ func resourceFirewallRead(d *schema.ResourceData, m interface{}) error { return nil } +// function to update the firewall func resourceFirewallUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) if d.HasChange("name") { if d.Get("name").(string) != "" { + log.Printf("[INFO] updating the firewall name, %s", d.Id()) _, err := apiClient.RenameFirewall(d.Id(), d.Get("name").(string)) if err != nil { - log.Printf("[WARN] an error occurred while trying to rename the firewall (%s)", d.Id()) + return fmt.Errorf("[WARN] an error occurred while tring to rename the firewall %s, %s", d.Id(), err) } } } @@ -79,12 +85,14 @@ func resourceFirewallUpdate(d *schema.ResourceData, m interface{}) error { return resourceFirewallRead(d, m) } +// function to delete a firewall func resourceFirewallDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the firewall %s", d.Id()) _, err := apiClient.DeleteFirewall(d.Id()) if err != nil { - log.Printf("[INFO] civo firewall (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete the firewall %s, %s", d.Id(), err) } return nil } diff --git a/civo/resource_firewall_rule.go b/civo/resource_firewall_rule.go index 4d006d2a..9f5eac2f 100644 --- a/civo/resource_firewall_rule.go +++ b/civo/resource_firewall_rule.go @@ -8,6 +8,9 @@ import ( "log" ) +// Firewall Rule resource represent you can create and manage all firewall rules +// this resource don't have a update option because the backend don't have the +// support for that, so in this case we use ForceNew for all object in the resource func resourceFirewallRule() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -70,21 +73,23 @@ func resourceFirewallRule() *schema.Resource { Create: resourceFirewallRuleCreate, Read: resourceFirewallRuleRead, Delete: resourceFirewallRuleDelete, - //Importer: &schema.ResourceImporter{ - // State: schema.ImportStatePassthrough, - //}, + Importer: &schema.ResourceImporter{ + State: resourceFirewallRuleImport, + }, } } +// function to create a new firewall rule func resourceFirewallRuleCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) - tfCidrs := d.Get("cird").(*schema.Set).List() - cird := make([]string, len(tfCidrs)) - for i, tfCird := range tfCidrs { + tfCidr := d.Get("cird").(*schema.Set).List() + cird := make([]string, len(tfCidr)) + for i, tfCird := range tfCidr { cird[i] = tfCird.(string) } + log.Printf("[INFO] configuring a new firewall rule for firewall %s", d.Get("firewall_id").(string)) config := &civogo.FirewallRuleConfig{ FirewallID: d.Get("firewall_id").(string), Protocol: d.Get("protocol").(string), @@ -101,6 +106,7 @@ func resourceFirewallRuleCreate(d *schema.ResourceData, m interface{}) error { config.Label = attr.(string) } + log.Printf("[INFO] creating a new firewall rule for firewall %s", d.Get("firewall_id").(string)) firewallRule, err := apiClient.NewFirewallRule(config) if err != nil { fmt.Errorf("[ERR] failed to create a new firewall: %s", err) @@ -112,9 +118,11 @@ func resourceFirewallRuleCreate(d *schema.ResourceData, m interface{}) error { return resourceFirewallRuleRead(d, m) } +// function to read a firewall rule func resourceFirewallRuleRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retriving the firewall rule %s", d.Id()) resp, err := apiClient.FindFirewallRule(d.Get("firewall_id").(string), d.Id()) if err != nil { if resp != nil { @@ -136,12 +144,43 @@ func resourceFirewallRuleRead(d *schema.ResourceData, m interface{}) error { return nil } +// function to delete a firewall rule func resourceFirewallRuleDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retriving the firewall rule %s", d.Id()) _, err := apiClient.DeleteFirewallRule(d.Get("firewall_id").(string), d.Id()) if err != nil { - log.Printf("[INFO] civo firewall rule (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete firewall rule %s", d.Id()) } return nil } + +// custom import to able to add a firewall rule to the terraform +func resourceFirewallRuleImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + apiClient := m.(*civogo.Client) + + firewallId, firewallRuleId, err := resourceCommonParseId(d.Id()) + if err != nil { + return nil, err + } + + log.Printf("[INFO] retriving the firewall rule %s", firewallRuleId) + resp, err := apiClient.FindFirewallRule(firewallId, firewallRuleId) + if err != nil { + if resp != nil { + return nil, err + } + } + + d.SetId(resp.ID) + d.Set("firewall_id", resp.FirewallID) + d.Set("protocol", resp.Protocol) + d.Set("start_port", resp.StartPort) + d.Set("end_port", resp.EndPort) + d.Set("cird", resp.Cidr) + d.Set("direction", resp.Direction) + d.Set("label", resp.Label) + + return []*schema.ResourceData{d}, nil +} diff --git a/civo/resource_instance.go b/civo/resource_instance.go index fb50e9a9..e226d909 100644 --- a/civo/resource_instance.go +++ b/civo/resource_instance.go @@ -9,6 +9,8 @@ import ( "strings" ) +// The instance resource represents an object of type instances +// and with it you can handle the instances created with Terraform func resourceInstance() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -108,12 +110,14 @@ func resourceInstance() *schema.Resource { } } +// function to create a instance func resourceInstanceCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] configuring the instance %s", d.Get("hostname").(string)) config, err := apiClient.NewInstanceConfig() if err != nil { - fmt.Errorf("failed to create a new config: %s", err) + fmt.Errorf("[ERR] failed to create a new config: %s", err) return err } @@ -155,14 +159,16 @@ func resourceInstanceCreate(d *schema.ResourceData, m interface{}) error { config.Tags = tags + log.Printf("[INFO] creating the instance %s", d.Get("hostname").(string)) instance, err := apiClient.CreateInstance(config) if err != nil { - fmt.Errorf("[WARN] failed to create instance: %s", err) + fmt.Errorf("[ERR] failed to create instance: %s", err) return err } d.SetId(instance.ID) + // retry to wait the instances is ready return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { resp, err := apiClient.GetInstance(instance.ID) if err != nil { @@ -170,7 +176,7 @@ func resourceInstanceCreate(d *schema.ResourceData, m interface{}) error { } if resp.Status != "ACTIVE" { - return resource.RetryableError(fmt.Errorf("[WARN] expected instance to be created but was in state %s", resp.Status)) + return resource.RetryableError(fmt.Errorf("[ERR] expected instance to be created but was in state %s", resp.Status)) } else { /* Once the instance is created, we check if the object firewall_id, @@ -179,7 +185,7 @@ func resourceInstanceCreate(d *schema.ResourceData, m interface{}) error { if attr, ok := d.GetOk("firewall_id"); ok { _, errInstance := apiClient.SetInstanceFirewall(instance.ID, attr.(string)) if errInstance != nil { - return resource.NonRetryableError(fmt.Errorf("[WARN] failed to set firewall to the instance: %s", errInstance)) + return resource.NonRetryableError(fmt.Errorf("[ERR] failed to set firewall to the instance: %s", errInstance)) } } @@ -191,7 +197,7 @@ func resourceInstanceCreate(d *schema.ResourceData, m interface{}) error { resp.Notes = attr.(string) _, errInstance := apiClient.UpdateInstance(resp) if errInstance != nil { - return resource.NonRetryableError(fmt.Errorf("[WARN] failed to set note to the instance: %s", errInstance)) + return resource.NonRetryableError(fmt.Errorf("[ERR] failed to set note to the instance: %s", errInstance)) } } } @@ -200,13 +206,15 @@ func resourceInstanceCreate(d *schema.ResourceData, m interface{}) error { }) } +// function to read the instance func resourceInstanceRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retriving the instance %s", d.Id()) resp, err := apiClient.GetInstance(d.Id()) if err != nil { // check if the instance no longer exists. - log.Printf("[WARN] civo instance (%s) not found", d.Id()) + fmt.Errorf("[ERR] instance (%s) not found", d.Id()) d.SetId("") return nil } @@ -222,7 +230,7 @@ func resourceInstanceRead(d *schema.ResourceData, m interface{}) error { d.Set("public_ip", resp.PublicIP) d.Set("pseudo_ip", resp.PseudoIP) d.Set("status", resp.Status) - d.Set("created_at", resp.CreatedAt.String()) + d.Set("created_at", resp.CreatedAt.UTC().String()) d.Set("notes", resp.Notes) if _, ok := d.GetOk("network_id"); ok { @@ -240,60 +248,66 @@ func resourceInstanceRead(d *schema.ResourceData, m interface{}) error { return nil } +// function to update a instance func resourceInstanceUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + // check if the size change if change we send to resize the instance if d.HasChange("size") { newSize := d.Get("size").(string) + + log.Printf("[INFO] resizing the instance %s", d.Id()) _, err := apiClient.UpgradeInstance(d.Id(), newSize) if err != nil { - log.Printf("[WARN] An error occurred while resizing the instance (%s)", d.Id()) + return fmt.Errorf("[WARN] An error occurred while resizing the instance %s", d.Id()) } return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { resp, err := apiClient.GetInstance(d.Id()) if err != nil { - return resource.NonRetryableError(fmt.Errorf("[WARN] error geting instance: %s", err)) + return resource.NonRetryableError(fmt.Errorf("[ERR] error geting instance: %s", err)) } if resp.Status != "ACTIVE" { - return resource.RetryableError(fmt.Errorf("[WARN] expected instance to be resizing but was in state %s", resp.Status)) + return resource.RetryableError(fmt.Errorf("[ERR] expected instance to be resizing but was in state %s", resp.Status)) } return resource.NonRetryableError(resourceInstanceRead(d, m)) }) } + // if has note we add to the instance if d.HasChange("notes") { notes := d.Get("notes").(string) instance, err := apiClient.GetInstance(d.Id()) if err != nil { // check if the instance no longer exists. - log.Printf("[WARN] civo instance (%s) not found", d.Id()) - d.SetId("") - return nil + return fmt.Errorf("[ERR] instance %s not found", d.Id()) } instance.Notes = notes + log.Printf("[INFO] adding notes to the instance %s", d.Id()) _, err = apiClient.UpdateInstance(instance) if err != nil { - log.Printf("[WARN] an error occurred while adding a note to the instance (%s)", d.Id()) + return fmt.Errorf("[ERR] an error occurred while adding a note to the instance %s", d.Id()) } } + // if a firewall is declare we update the instance if d.HasChange("firewall_id") { firewallID := d.Get("firewall_id").(string) + + log.Printf("[INFO] adding firewall to the instance %s", d.Id()) _, err := apiClient.SetInstanceFirewall(d.Id(), firewallID) if err != nil { // check if the instance no longer exists. - log.Printf("[WARN] an error occurred while set firewall to the instance (%s)", d.Id()) - d.SetId("") - return nil + return fmt.Errorf("[ERR] an error occurred while set firewall to the instance %s", d.Id()) } } + // if tags is declare we update the instance with the tags if d.HasChange("tags") { tfTags := d.Get("tags").(*schema.Set).List() tags := make([]string, len(tfTags)) @@ -304,16 +318,15 @@ func resourceInstanceUpdate(d *schema.ResourceData, m interface{}) error { instance, err := apiClient.GetInstance(d.Id()) if err != nil { // check if the instance no longer exists. - log.Printf("[WARN] civo instance (%s) not found", d.Id()) - d.SetId("") - return nil + return fmt.Errorf("[ERR] instance %s not found", d.Id()) } tagsToString := strings.Join(tags, " ") + log.Printf("[INFO] adding tags to the instance %s", d.Id()) _, err = apiClient.SetInstanceTags(instance, tagsToString) if err != nil { - log.Printf("[WARN] an error occurred while adding tags to the instance (%s)", d.Id()) + return fmt.Errorf("[ERR] an error occurred while adding tags to the instance %s", d.Id()) } } @@ -321,12 +334,14 @@ func resourceInstanceUpdate(d *schema.ResourceData, m interface{}) error { return resourceInstanceRead(d, m) } +// function to delete instance func resourceInstanceDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the instance %s", d.Id()) _, err := apiClient.DeleteInstance(d.Id()) if err != nil { - log.Printf("[INFO] civo instance (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete instance %s", d.Id()) } return nil } diff --git a/civo/resource_kubernetes_cluster.go b/civo/resource_kubernetes_cluster.go index dbaefc90..c85f7079 100644 --- a/civo/resource_kubernetes_cluster.go +++ b/civo/resource_kubernetes_cluster.go @@ -6,8 +6,10 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "log" ) +// Kubernetes Cluster resource, with this you can manage all cluster from terraform func resourceKubernetesCluster() *schema.Resource { return &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -83,9 +85,13 @@ func resourceKubernetesCluster() *schema.Resource { Read: resourceKubernetesClusterRead, Update: resourceKubernetesClusterUpdate, Delete: resourceKubernetesClusterDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, } } +// schema for the instances func instanceSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, @@ -130,6 +136,7 @@ func instanceSchema() *schema.Schema { } } +// schema for the application in the cluster func applicationSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, @@ -157,9 +164,11 @@ func applicationSchema() *schema.Schema { } } +// function to create a new cluster func resourceKubernetesClusterCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] configuring a new kubernetes cluster %s", d.Get("name").(string)) config := &civogo.KubernetesClusterConfig{ Name: d.Get("name").(string), TargetNodesSize: d.Get("target_nodes_size").(string), @@ -181,9 +190,10 @@ func resourceKubernetesClusterCreate(d *schema.ResourceData, m interface{}) erro config.Applications = attr.(string) } + log.Printf("[INFO] creating a new kubernetes cluster %s", d.Get("name").(string)) resp, err := apiClient.NewKubernetesClusters(config) if err != nil { - return fmt.Errorf("[WARN] failed to create the kubernets cluster: %s", err) + return fmt.Errorf("[ERR] failed to create the kubernets cluster: %s", err) } d.SetId(resp.ID) @@ -191,23 +201,25 @@ func resourceKubernetesClusterCreate(d *schema.ResourceData, m interface{}) erro return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { resp, err := apiClient.FindKubernetesCluster(d.Id()) if err != nil { - return resource.NonRetryableError(fmt.Errorf("[WARN] error geting kubernetes cluster: %s", err)) + return resource.NonRetryableError(fmt.Errorf("[ERR] error geting kubernetes cluster: %s", err)) } if resp.Ready != true { - return resource.RetryableError(fmt.Errorf("[WARN] waiting for the kubernets cluster to be created but the status is %s", resp.Status)) + return resource.RetryableError(fmt.Errorf("[ERR] waiting for the kubernets cluster to be created but the status is %s", resp.Status)) } return resource.NonRetryableError(resourceKubernetesClusterRead(d, m)) }) } +// function to read the kubernetes cluster func resourceKubernetesClusterRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retrieving the kubernetes cluster %s", d.Id()) resp, err := apiClient.FindKubernetesCluster(d.Id()) if err != nil { - return fmt.Errorf("[WARN] failed to find the kubernets cluster: %s", err) + return fmt.Errorf("[ERR] failed to find the kubernets cluster: %s", err) } d.Set("name", resp.Name) @@ -224,16 +236,17 @@ func resourceKubernetesClusterRead(d *schema.ResourceData, m interface{}) error d.Set("created_at", resp.CreatedAt.UTC().String()) if err := d.Set("instances", flattenInstances(resp.Instances)); err != nil { - return fmt.Errorf("[WARN] error retrieving the instances for kubernetes cluster error: %#v", err) + return fmt.Errorf("[ERR] error retrieving the instances for kubernetes cluster error: %#v", err) } if err := d.Set("installed_applications", flattenInstalledApplication(resp.InstalledApplications)); err != nil { - return fmt.Errorf("[WARN] error retrieving the installed application for kubernetes cluster error: %#v", err) + return fmt.Errorf("[ERR] error retrieving the installed application for kubernetes cluster error: %#v", err) } return nil } +// function to update the kubernetes cluster func resourceKubernetesClusterUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) @@ -246,36 +259,40 @@ func resourceKubernetesClusterUpdate(d *schema.ResourceData, m interface{}) erro config.Applications = d.Get("applications").(string) } + log.Printf("[INFO] updating the kubernetes cluster %s", d.Id()) _, err := apiClient.UpdateKubernetesCluster(d.Id(), config) if err != nil { - return fmt.Errorf("[WARN] failed to update kubernetes cluster: %s", err) + return fmt.Errorf("[ERR] failed to update kubernetes cluster: %s", err) } return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { resp, err := apiClient.FindKubernetesCluster(d.Id()) if err != nil { - return resource.NonRetryableError(fmt.Errorf("[WARN] error geting kubernetes cluster: %s", err)) + return resource.NonRetryableError(fmt.Errorf("[ERR] error geting kubernetes cluster: %s", err)) } if resp.Status != "ACTIVE" { - return resource.RetryableError(fmt.Errorf("[WARN] waiting for the kubernets cluster to be created but the status is %s", resp.Status)) + return resource.RetryableError(fmt.Errorf("[ERR] waiting for the kubernets cluster to be created but the status is %s", resp.Status)) } return resource.NonRetryableError(resourceKubernetesClusterRead(d, m)) }) } +// function to delete the kubernetes cluster func resourceKubernetesClusterDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the kubernetes cluster %s", d.Id()) _, err := apiClient.DeleteKubernetesCluster(d.Id()) if err != nil { - return fmt.Errorf("[INFO] kubernets cluster (%s) was delete", d.Id()) + return fmt.Errorf("[INFO] an error occurred while tring to delete the kubernetes cluster %s", err) } return nil } +// function to flatten all instances inside the cluster func flattenInstances(instances []civogo.KubernetesInstance) []interface{} { if instances == nil { return nil @@ -300,6 +317,7 @@ func flattenInstances(instances []civogo.KubernetesInstance) []interface{} { return flattenedInstances } +// function to flatten all applications inside the cluster func flattenInstalledApplication(apps []civogo.KubernetesInstalledApplication) []interface{} { if apps == nil { return nil diff --git a/civo/resource_loadbalance.go b/civo/resource_loadbalance.go index 7b08196b..578030f9 100644 --- a/civo/resource_loadbalance.go +++ b/civo/resource_loadbalance.go @@ -8,6 +8,7 @@ import ( "log" ) +// This resource represent a load balancer in the system func resourceLoadBalancer() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -123,9 +124,11 @@ func resourceLoadBalancer() *schema.Resource { } } +// function to create a new load balancer func resourceLoadBalancerCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] configuring the load balancer %s", d.Get("hostname").(string)) conf := &civogo.LoadBalancerConfig{ Hostname: d.Get("hostname").(string), Protocol: d.Get("protocol").(string), @@ -156,10 +159,10 @@ func resourceLoadBalancerCreate(d *schema.ResourceData, m interface{}) error { conf.IgnoreInvalidBackendTLS = v.(bool) } + log.Printf("[INFO] creating the load balancer %s", d.Get("hostname").(string)) lb, err := apiClient.CreateLoadBalancer(conf) if err != nil { - fmt.Errorf("[ERR] failed to create a new load balancer: %s", err) - return err + return fmt.Errorf("[ERR] failed to create a new load balancer: %s", err) } d.SetId(lb.ID) @@ -167,17 +170,18 @@ func resourceLoadBalancerCreate(d *schema.ResourceData, m interface{}) error { return resourceLoadBalancerRead(d, m) } +// function to read the load balancer func resourceLoadBalancerRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retrieving the load balancer %s", d.Id()) resp, err := apiClient.FindLoadBalancer(d.Id()) if err != nil { if resp != nil { d.SetId("") return nil } - - return fmt.Errorf("[WARN] error retrieving load balancer: %s", err) + return fmt.Errorf("[ERR] error retrieving load balancer: %s", err) } d.Set("hostname", resp.Hostname) @@ -193,15 +197,17 @@ func resourceLoadBalancerRead(d *schema.ResourceData, m interface{}) error { d.Set("ignore_invalid_backend_tls", resp.IgnoreInvalidBackendTLS) if err := d.Set("backend", flattenLoadBalancerBackend(resp.Backends)); err != nil { - return fmt.Errorf("[WARN] error retrieving the backend for load balancer error: %#v", err) + return fmt.Errorf("[ERR] error retrieving the backend for load balancer error: %#v", err) } return nil } +// function to update the load balancer func resourceLoadBalancerUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] configuring the load balancer to update %s", d.Id()) conf := &civogo.LoadBalancerConfig{ Hostname: d.Get("hostname").(string), Protocol: d.Get("protocol").(string), @@ -229,27 +235,29 @@ func resourceLoadBalancerUpdate(d *schema.ResourceData, m interface{}) error { conf.IgnoreInvalidBackendTLS = d.Get("ignore_invalid_backend_tls").(bool) } + log.Printf("[INFO] updating the load balancer %s", d.Id()) _, err := apiClient.UpdateLoadBalancer(d.Id(), conf) if err != nil { - fmt.Errorf("[WARN] failed to update load balancer: %s", err) - return err + return fmt.Errorf("[ERR] failed to update load balancer: %s", err) } return resourceLoadBalancerRead(d, m) } +// function to delete the load balancer func resourceLoadBalancerDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the load balancer %s", d.Id()) _, err := apiClient.DeleteLoadBalancer(d.Id()) if err != nil { - log.Printf("[INFO] Civo load balancer (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete load balancer %s", d.Id()) } return nil } -// Utils +// function to expand the load balancer backend to send to the api func expandLoadBalancerBackend(backend []interface{}) []civogo.LoadBalancerBackendConfig { expandedBackend := make([]civogo.LoadBalancerBackendConfig, 0, len(backend)) for _, rawBackend := range backend { @@ -267,6 +275,7 @@ func expandLoadBalancerBackend(backend []interface{}) []civogo.LoadBalancerBacke return expandedBackend } +// function to flatten the load balancer backend when is coming from the api func flattenLoadBalancerBackend(backend []civogo.LoadBalancerBackend) []interface{} { if backend == nil { return nil diff --git a/civo/resource_network.go b/civo/resource_network.go index 89226b89..434c32a9 100644 --- a/civo/resource_network.go +++ b/civo/resource_network.go @@ -7,6 +7,7 @@ import ( "log" ) +// The resource network represent a network inside the cloud func resourceNetwork() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -40,18 +41,20 @@ func resourceNetwork() *schema.Resource { Update: resourceNetworkUpdate, Delete: resourceNetworkDelete, //Exists: resourceExistsItem, - //Importer: &schema.ResourceImporter{ - // State: schema.ImportStatePassthrough, - //}, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, } } +// function to create a new network func resourceNetworkCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + + log.Printf("[INFO] creating the new network %s", d.Get("label").(string)) network, err := apiClient.NewNetwork(d.Get("label").(string)) if err != nil { - fmt.Errorf("failed to create a new config: %s", err) - return err + return fmt.Errorf("[ERR] failed to create a new network: %s", err) } d.SetId(network.ID) @@ -59,14 +62,16 @@ func resourceNetworkCreate(d *schema.ResourceData, m interface{}) error { return resourceNetworkRead(d, m) } +// function to read a network func resourceNetworkRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) CurrentNetwork := civogo.Network{} + log.Printf("[INFO] retriving the network %s", d.Id()) resp, err := apiClient.ListNetworks() if err != nil { - fmt.Errorf("failed to create a new config: %s", err) + return fmt.Errorf("[ERR] failed to list all network %s", err) } for _, net := range resp { @@ -84,27 +89,29 @@ func resourceNetworkRead(d *schema.ResourceData, m interface{}) error { return nil } +// function to update the network func resourceNetworkUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) if d.HasChange("label") { + log.Printf("[INFO] updating the network %s", d.Id()) _, err := apiClient.RenameNetwork(d.Get("label").(string), d.Id()) if err != nil { - log.Printf("[WARN] An error occurred while rename the network (%s)", d.Id()) + return fmt.Errorf("[ERR] An error occurred while rename the network %s", d.Id()) } - return resourceNetworkRead(d, m) } - return resourceNetworkRead(d, m) } +// function to delete a network func resourceNetworkDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the network %s", d.Id()) _, err := apiClient.DeleteNetwork(d.Id()) if err != nil { - log.Printf("[INFO] Civo network (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete the network %s", d.Id()) } return nil } diff --git a/civo/resource_snapshot.go b/civo/resource_snapshot.go index f371a30b..c7ee47a8 100644 --- a/civo/resource_snapshot.go +++ b/civo/resource_snapshot.go @@ -9,6 +9,9 @@ import ( "log" ) +// Snapshot resource, with this we can create and manage all Snapshot +// this resource dont have update option, we used ForceNew so any change +// in any value will be recreate the resource func resourceSnapshot() *schema.Resource { return &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -78,12 +81,17 @@ func resourceSnapshot() *schema.Resource { Create: resourceSnapshotCreate, Read: resourceSnapshotRead, Delete: resourceSnapshotDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, } } +// function to create a new snapshot func resourceSnapshotCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] configuring the new snapshot %s", d.Get("name").(string)) config := &civogo.SnapshotConfig{ InstanceID: d.Get("instance_id").(string), } @@ -96,10 +104,10 @@ func resourceSnapshotCreate(d *schema.ResourceData, m interface{}) error { config.Cron = attr.(string) } + log.Printf("[INFO] creating the new snapshot %s", d.Get("name").(string)) resp, err := apiClient.CreateSnapshot(d.Get("name").(string), config) if err != nil { - fmt.Errorf("[WARN] failed to create snapshot: %s", err) - return err + return fmt.Errorf("[ERR] failed to create snapshot: %s", err) } d.SetId(resp.ID) @@ -132,13 +140,14 @@ func resourceSnapshotCreate(d *schema.ResourceData, m interface{}) error { } +// function to read the snapshot func resourceSnapshotRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retrieving the snapshot %s", d.Get("name").(string)) resp, err := apiClient.FindSnapshot(d.Id()) if err != nil { - fmt.Errorf("[WARN] failed to read snapshot: %s", err) - return err + return fmt.Errorf("[ERR] failed retrieving the snapshot: %s", err) } safeValue := false @@ -156,18 +165,20 @@ func resourceSnapshotRead(d *schema.ResourceData, m interface{}) error { d.Set("size_gb", resp.SizeGigabytes) d.Set("state", resp.State) d.Set("cron_timing", resp.Cron) - d.Set("requested_at", resp.RequestedAt.String()) - d.Set("completed_at", resp.CompletedAt.String()) + d.Set("requested_at", resp.RequestedAt.UTC().String()) + d.Set("completed_at", resp.CompletedAt.UTC().String()) return nil } +// function to delete snapshot func resourceSnapshotDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the snapshot %s", d.Id()) _, err := apiClient.DeleteSnapshot(d.Id()) if err != nil { - log.Printf("[INFO] civo snapshot (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete the snapshot %s", d.Id()) } return nil diff --git a/civo/resource_ssh.go b/civo/resource_ssh.go index cfe89121..ac66a178 100644 --- a/civo/resource_ssh.go +++ b/civo/resource_ssh.go @@ -7,6 +7,7 @@ import ( "log" ) +// Ssh resource, with this we can create and manage all Snapshot func resourceSSHKey() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -40,13 +41,14 @@ func resourceSSHKey() *schema.Resource { } } +// function to create a new ssh key func resourceSSHKeyCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] creating the new ssh key %s", d.Get("name").(string)) sshKey, err := apiClient.NewSSHKey(d.Get("name").(string), d.Get("public_key").(string)) if err != nil { - fmt.Errorf("[WARN] failed to create a new ssh key: %s", err) - return err + return fmt.Errorf("[ERR] failed to create a new ssh key: %s", err) } d.SetId(sshKey.ID) @@ -54,9 +56,11 @@ func resourceSSHKeyCreate(d *schema.ResourceData, m interface{}) error { return resourceSSHKeyRead(d, m) } +// function to read a ssh key func resourceSSHKeyRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retrieving the new ssh key %s", d.Get("name").(string)) sshKey, err := apiClient.FindSSHKey(d.Id()) if err != nil { if sshKey != nil { @@ -64,7 +68,7 @@ func resourceSSHKeyRead(d *schema.ResourceData, m interface{}) error { return nil } - return fmt.Errorf("[WARN] error retrieving ssh key: %s", err) + return fmt.Errorf("[ERR] error retrieving ssh key: %s", err) } d.Set("name", sshKey.Name) @@ -73,14 +77,16 @@ func resourceSSHKeyRead(d *schema.ResourceData, m interface{}) error { return nil } +// function to update the ssh key func resourceSSHKeyUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) if d.HasChange("name") { if d.Get("name").(string) != "" { + log.Printf("[INFO] updating the ssh key %s", d.Get("name").(string)) _, err := apiClient.UpdateSSHKey(d.Get("name").(string), d.Id()) if err != nil { - log.Printf("[WARN] an error occurred while trying to rename the ssh key (%s)", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to rename the ssh key %s", d.Id()) } } } @@ -88,12 +94,14 @@ func resourceSSHKeyUpdate(d *schema.ResourceData, m interface{}) error { return resourceSSHKeyRead(d, m) } +// function to delete the ssh key func resourceSSHKeyDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the ssh key %s", d.Id()) _, err := apiClient.DeleteSSHKey(d.Id()) if err != nil { - log.Printf("[INFO] civo ssh key (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete the ssh key %s", d.Id()) } return nil } diff --git a/civo/resource_template.go b/civo/resource_template.go index 79d49dc4..e9c4d82e 100644 --- a/civo/resource_template.go +++ b/civo/resource_template.go @@ -8,6 +8,7 @@ import ( "log" ) +// Template resource, with this we can create and manage all template func resourceTemplate() *schema.Resource { return &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -73,9 +74,13 @@ func resourceTemplate() *schema.Resource { Read: resourceTemplateRead, Update: resourceTemplateUpdate, Delete: resourceTemplateDelete, + Importer: &schema.ResourceImporter{ + State: resourceTemplateImport, + }, } } +// function to create a new template func resourceTemplateCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) @@ -91,6 +96,7 @@ func resourceTemplateCreate(d *schema.ResourceData, m interface{}) error { return fmt.Errorf("`volume_id` or `image_id` must be assigned") } + log.Printf("[INFO] configuring the template %s", d.Get("code").(string)) config := &civogo.Template{ Code: d.Get("code").(string), Name: d.Get("name").(string), @@ -120,10 +126,10 @@ func resourceTemplateCreate(d *schema.ResourceData, m interface{}) error { config.CloudConfig = attr.(string) } + log.Printf("[INFO] creating the template %s", d.Get("code").(string)) resp, err := apiClient.NewTemplate(config) if err != nil { - fmt.Errorf("[WARN] failed to create template: %s", err) - return err + return fmt.Errorf("[ERR] failed to create template: %s", err) } d.SetId(resp.ID) @@ -131,13 +137,14 @@ func resourceTemplateCreate(d *schema.ResourceData, m interface{}) error { return resourceTemplateRead(d, m) } +// function to read a template func resourceTemplateRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] retrieving the template %s", d.Get("code").(string)) resp, err := apiClient.GetTemplateByCode(d.Get("code").(string)) if err != nil { - fmt.Errorf("[WARN] failed to read template: %s", err) - return err + return fmt.Errorf("[ERR] failed to retrieving the template: %s", err) } d.Set("code", resp.Code) @@ -152,9 +159,11 @@ func resourceTemplateRead(d *schema.ResourceData, m interface{}) error { return nil } +// function to update the template func resourceTemplateUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] configuring the template %s", d.Get("code").(string)) conf := &civogo.Template{ Name: d.Get("name").(string), ShortDescription: d.Get("short_description").(string), @@ -165,22 +174,49 @@ func resourceTemplateUpdate(d *schema.ResourceData, m interface{}) error { ImageID: d.Get("image_id").(string), } + log.Printf("[INFO] updating the template %s", d.Get("code").(string)) _, err := apiClient.UpdateTemplate(d.Id(), conf) if err != nil { - fmt.Errorf("[WARN] failed to update template: %s", err) - return err + return fmt.Errorf("[ERR] failed to update template: %s", err) } return resourceTemplateRead(d, m) } +// function to delete the template func resourceTemplateDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the template %s", d.Id()) _, err := apiClient.DeleteTemplate(d.Id()) if err != nil { - log.Printf("[INFO] civo template (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete the template %s", d.Id()) } return nil } + +// custom import to able to add a template to the terraform +func resourceTemplateImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + apiClient := m.(*civogo.Client) + + log.Printf("[INFO] retriving the template %s", d.Id()) + resp, err := apiClient.GetTemplateByCode(d.Id()) + if err != nil { + if resp != nil { + return nil, err + } + } + + d.SetId(resp.ID) + d.Set("code", resp.Code) + d.Set("name", resp.Name) + d.Set("volume_id", resp.VolumeID) + d.Set("image_id", resp.ImageID) + d.Set("short_description", resp.ShortDescription) + d.Set("description", resp.Description) + d.Set("default_username", resp.DefaultUsername) + d.Set("cloud_config", resp.CloudConfig) + + return []*schema.ResourceData{d}, nil +} diff --git a/civo/resource_volume.go b/civo/resource_volume.go index 7b6e6bea..e78af3bc 100644 --- a/civo/resource_volume.go +++ b/civo/resource_volume.go @@ -9,6 +9,7 @@ import ( "time" ) +// Volume resource, with this we can create and manage all volume func resourceVolume() *schema.Resource { fmt.Print() return &schema.Resource{ @@ -49,20 +50,22 @@ func resourceVolume() *schema.Resource { Update: resourceVolumeUpdate, Delete: resourceVolumeDelete, //Exists: resourceExistsItem, - //Importer: &schema.ResourceImporter{ - // State: schema.ImportStatePassthrough, - //}, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, } } +// function to create the new volume func resourceVolumeCreate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] configuring the volume %s", d.Get("name").(string)) config := &civogo.VolumeConfig{Name: d.Get("name").(string), SizeGigabytes: d.Get("size_gb").(int), Bootable: d.Get("bootable").(bool)} volume, err := apiClient.NewVolume(config) if err != nil { - return fmt.Errorf("failed to create a new config: %s", err) + return fmt.Errorf("[ERR] failed to create a new config: %s", err) } d.SetId(volume.ID) @@ -70,39 +73,34 @@ func resourceVolumeCreate(d *schema.ResourceData, m interface{}) error { if d.Get("instance_id").(string) != "" { _, err := apiClient.AttachVolume(d.Id(), d.Get("instance_id").(string)) if err != nil { - log.Printf("[WARN] An error occurred while trying to attach the volume (%s)", d.Id()) + return fmt.Errorf("[ERR] An error occurred while tring to attach the volume (%s)", d.Id()) } } return resourceNetworkRead(d, m) } +// function to read the volume func resourceVolumeRead(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) - CurrentVolume := civogo.Volume{} - - resp, err := apiClient.ListVolumes() + log.Printf("[INFO] retrieving the template %s", d.Id()) + resp, err := apiClient.FindVolume(d.Id()) if err != nil { - return fmt.Errorf("failed to create a new config: %s", err) - } - - for _, volume := range resp { - if volume.ID == d.Id() { - CurrentVolume = volume - } + return fmt.Errorf("[ERR] failed retrieving the volume: %s", err) } - d.Set("name", CurrentVolume.Name) - d.Set("size_gb", CurrentVolume.SizeGigabytes) - d.Set("bootable", CurrentVolume.Bootable) - d.Set("instance_id", CurrentVolume.InstanceID) - d.Set("mount_point", CurrentVolume.MountPoint) - d.Set("created_at", CurrentVolume.CreatedAt) + d.Set("name", resp.Name) + d.Set("size_gb", resp.SizeGigabytes) + d.Set("bootable", resp.Bootable) + d.Set("instance_id", resp.InstanceID) + d.Set("mount_point", resp.MountPoint) + d.Set("created_at", resp.CreatedAt.UTC().String()) return nil } +// function to update the volume func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) @@ -110,7 +108,7 @@ func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error { if d.Get("instance_id").(string) != "" { _, err := apiClient.AttachVolume(d.Id(), d.Get("instance_id").(string)) if err != nil { - log.Printf("[WARN] An error occurred while trying to attach the volume (%s)", d.Id()) + return fmt.Errorf("[WARN] An error occurred while tring to attach the volume %s, %s", d.Id(), err) } return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { @@ -118,7 +116,7 @@ func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error { resp, err := apiClient.ListVolumes() if err != nil { - return resource.NonRetryableError(fmt.Errorf("failed to get all volume: %s", err)) + return resource.NonRetryableError(fmt.Errorf("[ERR] failed to get all volume: %s", err)) } for _, volume := range resp { @@ -128,7 +126,7 @@ func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error { } if CurrentVolume.MountPoint != "" { - return resource.RetryableError(fmt.Errorf("expected volume to be mount but was in state %s", CurrentVolume.MountPoint)) + return resource.RetryableError(fmt.Errorf("expected volume to be mount but the mount point is %s", CurrentVolume.MountPoint)) } return resource.NonRetryableError(resourceVolumeRead(d, m)) @@ -138,7 +136,7 @@ func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error { if d.Get("instance_id").(string) == "" { _, err := apiClient.DetachVolume(d.Id()) if err != nil { - log.Printf("[WARN] An error occurred while trying to detach volume (%s)", d.Id()) + return fmt.Errorf("[ERR] An error occurred while tring to detach volume (%s)", d.Id()) } return resourceVolumeRead(d, m) @@ -150,7 +148,7 @@ func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error { if d.Get("instance_id").(string) != "" { _, err := apiClient.DetachVolume(d.Id()) if err != nil { - log.Printf("[WARN] An error occurred while trying to detach volume (%s)", d.Id()) + return fmt.Errorf("[WARN] an error occurred while tring to detach volume %s, %s", d.Id(), err) } time.Sleep(10 * time.Second) @@ -158,14 +156,14 @@ func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error { newSize := d.Get("size_gb").(int) _, err = apiClient.ResizeVolume(d.Id(), newSize) if err != nil { - log.Printf("[INFO] Civo volume (%s) size not change", d.Id()) + return fmt.Errorf("[ERR] the volume (%s) size not change %s", d.Id(), err) } time.Sleep(2 * time.Second) _, err = apiClient.AttachVolume(d.Id(), d.Get("instance_id").(string)) if err != nil { - log.Printf("[WARN] An error occurred while trying to attach the volume (%s)", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to attach the volume %s", d.Id()) } } @@ -175,12 +173,14 @@ func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error { return resourceVolumeRead(d, m) } +// function to delete the volume func resourceVolumeDelete(d *schema.ResourceData, m interface{}) error { apiClient := m.(*civogo.Client) + log.Printf("[INFO] deleting the volume %s", d.Id()) _, err := apiClient.DeleteVolume(d.Id()) if err != nil { - log.Printf("[INFO] Civo volume (%s) was delete", d.Id()) + return fmt.Errorf("[ERR] an error occurred while tring to delete the volume %s", err) } return nil } diff --git a/civo/utils.go b/civo/utils.go index 0286716a..e29d9be6 100644 --- a/civo/utils.go +++ b/civo/utils.go @@ -3,6 +3,7 @@ package civo import ( "fmt" "regexp" + "strings" ) func validateName(v interface{}, k string) (ws []string, es []error) { @@ -20,3 +21,14 @@ func validateName(v interface{}, k string) (ws []string, es []error) { } return warns, errs } + +// util function to help the import function +func resourceCommonParseId(id string) (string, string, error) { + parts := strings.SplitN(id, ":", 2) + + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "", "", fmt.Errorf("unexpected format of ID (%s), expected attribute1:attribute2", id) + } + + return parts[0], parts[1], nil +} diff --git a/go.mod b/go.mod index 55265b77..a0bd95c0 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/civo/terraform-provider-civo require ( cloud.google.com/go v0.54.0 // indirect github.com/aws/aws-sdk-go v1.29.22 // indirect - github.com/civo/civogo v0.2.4 + github.com/civo/civogo v0.2.5 github.com/fatih/color v1.9.0 // indirect github.com/hashicorp/go-getter v1.4.1 // indirect github.com/hashicorp/go-hclog v0.12.1 // indirect diff --git a/go.sum b/go.sum index a09002a7..28575381 100644 --- a/go.sum +++ b/go.sum @@ -73,6 +73,8 @@ github.com/civo/civogo v0.2.3 h1:BYLWgEDr/Wh/IcijFAA82VyarSvBzWfATyXgnKcjx9s= github.com/civo/civogo v0.2.3/go.mod h1:SR0ZOhABfQHjgNQE3UyfX4gaYsrfslkPFRFMx5P29rg= github.com/civo/civogo v0.2.4 h1:V7LLe7aPfQs+XZ4xq+6TOnf9CU7Y9iH3jgfma1WkcFk= github.com/civo/civogo v0.2.4/go.mod h1:SR0ZOhABfQHjgNQE3UyfX4gaYsrfslkPFRFMx5P29rg= +github.com/civo/civogo v0.2.5 h1:HOObmjirSPoTwJDsZWQeKnEJE00OBvKrC1wjqE4ZhNs= +github.com/civo/civogo v0.2.5/go.mod h1:SR0ZOhABfQHjgNQE3UyfX4gaYsrfslkPFRFMx5P29rg= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=