diff --git a/gcore/resource_gcore_k8sv2.go b/gcore/resource_gcore_k8sv2.go index badb2af..0e4f4f1 100644 --- a/gcore/resource_gcore_k8sv2.go +++ b/gcore/resource_gcore_k8sv2.go @@ -2,6 +2,7 @@ package gcore import ( "context" + "encoding/json" "fmt" "log" "reflect" @@ -624,6 +625,10 @@ func resourceK8sV2Update(ctx context.Context, d *schema.ResourceData, m interfac o, n := d.GetChange("pool") old, new := o.([]interface{}), n.([]interface{}) + if err := resourceK8sV2CheckLimits(client, old, new); err != nil { + return diag.FromErr(err) + } + // Any new pools must be created first, so that "replace" can safely delete pools that it will recreate. // This also covers pools that were renamed, because pool name must be unique. for _, pool := range new { @@ -929,3 +934,54 @@ func resourceK8sV2FilteredPoolLabels(labels map[string]string) map[string]string func resourceK8sV2IsVMFlavor(flavor string) bool { return strings.HasPrefix(flavor, "g") || strings.HasPrefix(flavor, "a") } + +func resourceK8sV2CheckLimits(client *gcorecloud.ServiceClient, old, new []interface{}) error { + log.Printf("[DEBUG] Checking quota limits") + + opts := &clusters.CheckLimitsOpts{} + for _, n := range new { + newPool, ok := n.(map[string]interface{}) + if !ok || len(newPool) == 0 { + continue + } + if resourceK8sV2FindClusterPool(old, newPool) == nil || resourceK8sV2ClusterPoolNeedsReplace(old, newPool) { + poolOpts := clusters.CheckLimitsPoolOpts{ + Name: newPool["name"].(string), + FlavorID: newPool["flavor_id"].(string), + MinNodeCount: newPool["min_node_count"].(int), + MaxNodeCount: newPool["max_node_count"].(int), + BootVolumeSize: newPool["boot_volume_size"].(int), + ServerGroupPolicy: servergroups.ServerGroupPolicy(newPool["servergroup_policy"].(string)), + } + opts.Pools = append(opts.Pools, poolOpts) + } else if resourceK8sV2ClusterPoolNeedsUpdate(old, newPool) { + oldPool := resourceK8sV2FindClusterPool(old, newPool).(map[string]interface{}) + minCount := newPool["min_node_count"].(int) - oldPool["min_node_count"].(int) + maxCount := newPool["max_node_count"].(int) - oldPool["max_node_count"].(int) + if minCount <= 0 { + continue + } + poolOpts := clusters.CheckLimitsPoolOpts{ + Name: newPool["name"].(string), + FlavorID: newPool["flavor_id"].(string), + MinNodeCount: minCount, + MaxNodeCount: maxCount, + BootVolumeSize: newPool["boot_volume_size"].(int), + ServerGroupPolicy: servergroups.ServerGroupPolicy(newPool["servergroup_policy"].(string)), + } + opts.Pools = append(opts.Pools, poolOpts) + } + } + + if len(opts.Pools) > 0 { + quota, err := clusters.CheckLimits(client, opts).Extract() + if err != nil { + return fmt.Errorf("check limits: %w", err) + } + if len(*quota) > 0 { + b, _ := json.Marshal(quota) // pretty print map + return fmt.Errorf("quota limits exceeded for this operation: %s", string(b)) + } + } + return nil +} diff --git a/go.mod b/go.mod index df1ac54..a4b4ab8 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/G-Core/gcore-dns-sdk-go v0.2.9 github.com/G-Core/gcore-storage-sdk-go v0.1.34 github.com/G-Core/gcorelabscdn-go v1.0.14 - github.com/G-Core/gcorelabscloud-go v0.7.15 + github.com/G-Core/gcorelabscloud-go v0.7.16 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0 github.com/mitchellh/mapstructure v1.5.0 @@ -50,7 +50,6 @@ require ( github.com/hashicorp/hcl/v2 v2.17.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-json v0.21.0 // indirect - github.com/hashicorp/terraform-plugin-docs v0.19.2 // indirect github.com/hashicorp/terraform-plugin-go v0.16.0 // indirect github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.1 // indirect diff --git a/go.sum b/go.sum index ab04eaa..65daa9b 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/G-Core/gcore-storage-sdk-go v0.1.34 h1:0GPQfz1kA6mQi6fiisGsh0Um4H9PZe github.com/G-Core/gcore-storage-sdk-go v0.1.34/go.mod h1:BUAEZZZJJt/+luRFunqziv3+JnbVMLbQXDWz9kV8Te8= github.com/G-Core/gcorelabscdn-go v1.0.14 h1:s34XWrMeuR/TvmnN0jrb6vsC9IzQFGFhb+qlxTbOfq8= github.com/G-Core/gcorelabscdn-go v1.0.14/go.mod h1:iSGXaTvZBzDHQW+rKFS918BgFVpONcyLEijwh8WsXpE= -github.com/G-Core/gcorelabscloud-go v0.7.15 h1:HZrXK5hTqTzh4yZyCDkOKXhduZ2dp/NU/B+hhkgj6B4= -github.com/G-Core/gcorelabscloud-go v0.7.15/go.mod h1:13Z1USxlxPbDFuYQyWqfNexlk4kUvOYTXbnvV/Z1lZo= +github.com/G-Core/gcorelabscloud-go v0.7.16 h1:Kv2qa4GtDkpefYkRP5oSCfvtpaZdFrIl/Wcze/LGwOg= +github.com/G-Core/gcorelabscloud-go v0.7.16/go.mod h1:13Z1USxlxPbDFuYQyWqfNexlk4kUvOYTXbnvV/Z1lZo= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=