Skip to content

Commit

Permalink
feat: Add other data resource, k8s version, instances size
Browse files Browse the repository at this point in the history
- Add kubernetes version like data source
- Add Instances size like data source
- Add datasource_common_schema.go and datasource_common_struct.go to support kubernetes version and instances size data source

BREAKING CHANGE: No

Signed-off-by: Alejandro JNM <alejandrojnm@gmail.com>
  • Loading branch information
alejandrojnm committed Apr 11, 2020
1 parent 0892984 commit 77c3d35
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 13 deletions.
31 changes: 31 additions & 0 deletions civo/datasource_common_schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package civo

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

func dataSourceFiltersSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"values": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"regex": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
},
}
}
7 changes: 7 additions & 0 deletions civo/datasource_common_struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package civo

type Filter struct {
Name string
Values []string
Regex bool
}
165 changes: 165 additions & 0 deletions civo/datasource_intances_size.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package civo

import (
"fmt"
"github.com/civo/civogo"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"regexp"
"strconv"
)

func dataSourceInstancesSize() *schema.Resource {
return &schema.Resource{
Read: dataSourceInstancesSizeRead,
Schema: map[string]*schema.Schema{
"filter": dataSourceFiltersSchema(),
// computed attributes
"name": {
Type: schema.TypeString,
Computed: true,
},
"nice_name": {
Type: schema.TypeString,
Computed: true,
},
"cpu_cores": {
Type: schema.TypeInt,
Computed: true,
},
"ram_mb": {
Type: schema.TypeInt,
Computed: true,
},
"disk_gb": {
Type: schema.TypeInt,
Computed: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"selectable": {
Type: schema.TypeBool,
Computed: true,
},
},
}
}

func dataSourceInstancesSizeRead(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*civogo.Client)

filters, filtersOk := d.GetOk("filter")

if !filtersOk {
return fmt.Errorf("one of filters must be assigned")
}

if filtersOk {
resp, err := apiClient.ListInstanceSizes()
if err != nil {
return fmt.Errorf("no instances size was found in the server")
}

size, err := findInstancesSizeByFilter(resp, filters.(*schema.Set))
if err != nil {
return fmt.Errorf("no instances size was found in the server, %s", err)
}

d.SetId(size.ID)
d.Set("name", size.Name)
d.Set("nice_name", size.NiceName)
d.Set("cpu_cores", size.CPUCores)
d.Set("ram_mb", size.RAMMegabytes)
d.Set("disk_gb", size.DiskGigabytes)
d.Set("description", size.Description)
d.Set("selectable", size.Selectable)
}

return nil
}

func findInstancesSizeByFilter(sizes []civogo.InstanceSize, set *schema.Set) (*civogo.InstanceSize, error) {
results := make([]civogo.InstanceSize, 0)

var filters []Filter

for _, v := range set.List() {
m := v.(map[string]interface{})
var filterValues []string
for _, e := range m["values"].([]interface{}) {
filterValues = append(filterValues, e.(string))
}
filters = append(filters, Filter{Name: m["name"].(string), Values: filterValues, Regex: m["regex"].(bool)})
}

for _, valueFilters := range filters {
for _, valueSize := range sizes {

// filter for the name
if valueFilters.Name == "name" {
if valueFilters.Regex {
r, _ := regexp.Compile(valueFilters.Values[0])
if r.MatchString(valueSize.Name) {
results = append(results, valueSize)
}
} else {
if valueSize.Name == valueFilters.Values[0] {
results = append(results, valueSize)
}
}
}

// filter for the CPU
if valueFilters.Name == "cpu" {
if valueFilters.Regex {
r, _ := regexp.Compile(valueFilters.Values[0])
if r.MatchString(strconv.Itoa(valueSize.CPUCores)) {
results = append(results, valueSize)
}
} else {
if strconv.Itoa(valueSize.CPUCores) == valueFilters.Values[0] {
results = append(results, valueSize)
}
}
}

// filter for the RAM
if valueFilters.Name == "ram" {
if valueFilters.Regex {
r, _ := regexp.Compile(valueFilters.Values[0])
if r.MatchString(strconv.Itoa(valueSize.RAMMegabytes)) {
results = append(results, valueSize)
}
} else {
if strconv.Itoa(valueSize.RAMMegabytes) == valueFilters.Values[0] {
results = append(results, valueSize)
}
}
}

// filter for the Disk
if valueFilters.Name == "disk" {
if valueFilters.Regex {
r, _ := regexp.Compile(valueFilters.Values[0])
if r.MatchString(strconv.Itoa(valueSize.DiskGigabytes)) {
results = append(results, valueSize)
}
} else {
if strconv.Itoa(valueSize.DiskGigabytes) == valueFilters.Values[0] {
results = append(results, valueSize)
}
}
}

}
}

if len(results) == 1 {
return &results[0], nil
}
if len(results) == 0 {
return nil, fmt.Errorf("no sizes found for your search")
}
return nil, fmt.Errorf("too many sizes found (found %d, expected 1)", len(results))
}
105 changes: 105 additions & 0 deletions civo/datasource_kubernetes_version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package civo

import (
"fmt"
"github.com/civo/civogo"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func dataSourceKubernetesVersion() *schema.Resource {
return &schema.Resource{
Read: dataSourceKubernetesVersionRead,
Schema: map[string]*schema.Schema{
"filter": dataSourceFiltersSchema(),
// computed attributes
"version": {
Type: schema.TypeString,
Computed: true,
},
"label": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"default": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceKubernetesVersionRead(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*civogo.Client)

filters, filtersOk := d.GetOk("filter")

if !filtersOk {
return fmt.Errorf("one of filters must be assigned")
}

if filtersOk {
resp, err := apiClient.ListAvailableKubernetesVersions()
if err != nil {
return fmt.Errorf("no version was found in the server")
}

version, err := findKubernetesVersionByFilter(resp, filters.(*schema.Set))
if err != nil {
return fmt.Errorf("no version was found in the server, %s", err)
}

d.SetId(version.Version)
d.Set("version", version.Version)
d.Set("label", fmt.Sprintf("v%s", version.Version))
d.Set("type", version.Type)
d.Set("default", version.Default)
}

return nil
}

func findKubernetesVersionByFilter(version []civogo.KubernetesVersion, set *schema.Set) (*civogo.KubernetesVersion, error) {
results := make([]civogo.KubernetesVersion, 0)

var filters []Filter

for _, v := range set.List() {
m := v.(map[string]interface{})
var filterValues []string
for _, e := range m["values"].([]interface{}) {
filterValues = append(filterValues, e.(string))
}
filters = append(filters, Filter{Name: m["name"].(string), Values: filterValues, Regex: m["regex"].(bool)})
}

for _, valueFilters := range filters {
for _, valueVersion := range version {

// Filter for version
if valueFilters.Name == "version" {
if valueVersion.Version == valueFilters.Values[0] {
results = append(results, valueVersion)
}
}

// Filter for type
if valueFilters.Name == "type" {
if valueVersion.Type == valueFilters.Values[0] {
results = append(results, valueVersion)
}
}
}
}

if len(results) == 1 {
return &results[0], nil
}
if len(results) == 0 {
return nil, fmt.Errorf("no version found for your search")
}
return nil, fmt.Errorf("too many version found (found %d, expected 1)", len(results))
}
4 changes: 3 additions & 1 deletion civo/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ func Provider() terraform.ResourceProvider {
},
},
DataSourcesMap: map[string]*schema.Resource{
"civo_template": dataSourceTemplate(),
"civo_template": dataSourceTemplate(),
"civo_kubernetes_version": dataSourceKubernetesVersion(),
"civo_instances_size": dataSourceInstancesSize(),
},
ResourcesMap: map[string]*schema.Resource{
"civo_instance": resourceInstance(),
Expand Down
31 changes: 19 additions & 12 deletions civo/resource_kubernetes_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func resourceKubernetesCluster() *schema.Resource {
"kubernetes_version": {
Type: schema.TypeString,
Optional: true,
Default: "1.0.0",
Description: "the version of k3s to install (optional, the default is currently the latest available)",
},
"tags": {
Expand Down Expand Up @@ -188,7 +189,7 @@ func resourceKubernetesClusterCreate(d *schema.ResourceData, m interface{}) erro
d.SetId(resp.ID)

return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
resp, err := apiClient.FindKubernetesCluster(d.Get("name").(string))
resp, err := apiClient.FindKubernetesCluster(d.Id())
if err != nil {
return resource.NonRetryableError(fmt.Errorf("[WARN] error geting kubernetes cluster: %s", err))
}
Expand Down Expand Up @@ -236,26 +237,32 @@ func resourceKubernetesClusterRead(d *schema.ResourceData, m interface{}) error
func resourceKubernetesClusterUpdate(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*civogo.Client)

config := &civogo.KubernetesClusterConfig{
Name: d.Get("name").(string),
TargetNodesSize: d.Get("target_nodes_size").(string),
}
config := &civogo.KubernetesClusterConfig{}

if d.HasChange("num_target_nodes") {
if d.HasChange("num_target_nodes") || d.HasChange("kubernetes_version") || d.HasChange("applications") || d.HasChange("name") {
config.Name = d.Get("name").(string)
config.NumTargetNodes = d.Get("num_target_nodes").(int)
}

if d.HasChange("applications") {
config.KubernetesVersion = d.Get("kubernetes_version").(string)
config.Applications = d.Get("applications").(string)
}

_, err := apiClient.UpdateKubernetesCluster(d.Id(), config)
if err != nil {
fmt.Errorf("[WARN] failed to update load balancer: %s", err)
return err
return fmt.Errorf("[WARN] failed to update kubernetes cluster: %s", err)
}

return resourceKubernetesClusterRead(d, m)
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))
}

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.NonRetryableError(resourceKubernetesClusterRead(d, m))
})
}

func resourceKubernetesClusterDelete(d *schema.ResourceData, m interface{}) error {
Expand Down

0 comments on commit 77c3d35

Please sign in to comment.