-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add selectel_dbaas_firewall_v1 resource
- Make firewall field for datastore resources deprecated. Because, we cannot change firewall state during creation of the datastore only after - Add a new selectel_dbaas_firewall_v1 resource to manage datastore's firewall
- Loading branch information
Showing
12 changed files
with
360 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
package selectel | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"log" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/selectel/dbaas-go" | ||
schemas "github.com/terraform-providers/terraform-provider-selectel/selectel/schemas/dbaas" | ||
waiters "github.com/terraform-providers/terraform-provider-selectel/selectel/waiters/dbaas" | ||
) | ||
|
||
func resourceDBaaSFirewallV1() *schema.Resource { | ||
return &schema.Resource{ | ||
CreateContext: resourceDBaaSFirewallV1Update, | ||
ReadContext: resourceDBaaSFirewallV1Read, | ||
UpdateContext: resourceDBaaSFirewallV1Update, | ||
DeleteContext: resourceDBaaSFirewallV1Delete, | ||
Importer: &schema.ResourceImporter{ | ||
StateContext: resourceDBaaSFirewallV1ImportState, | ||
}, | ||
Timeouts: &schema.ResourceTimeout{ | ||
Create: schema.DefaultTimeout(60 * time.Minute), | ||
Update: schema.DefaultTimeout(60 * time.Minute), | ||
Delete: schema.DefaultTimeout(60 * time.Minute), | ||
}, | ||
Schema: schemas.ResourceDBaaSFirewallV1Schema(), | ||
} | ||
} | ||
|
||
func resourceDBaaSFirewallV1Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
datastoreID := d.Get("datastore_id").(string) | ||
|
||
dbaasClient, diagErr := getDBaaSClient(d, meta) | ||
if diagErr != nil { | ||
return diagErr | ||
} | ||
|
||
rawIPs := d.Get("ips").([]interface{}) | ||
firewallOpts, err := resourceDBaaSDatastoreV1FirewallOptsFromList(rawIPs) | ||
if err != nil { | ||
return diag.FromErr(errParseDatastoreV1Firewall(err)) | ||
} | ||
|
||
log.Print(msgUpdate(objectDatastore, datastoreID, firewallOpts)) | ||
_, err = dbaasClient.FirewallDatastore(ctx, datastoreID, firewallOpts) | ||
if err != nil { | ||
return diag.FromErr(errUpdatingObject(objectDatastore, datastoreID, err)) | ||
} | ||
|
||
log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", datastoreID) | ||
timeout := d.Timeout(schema.TimeoutUpdate) | ||
err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastoreID, timeout) | ||
if err != nil { | ||
return diag.FromErr(errUpdatingObject(objectDatastore, datastoreID, err)) | ||
} | ||
|
||
return resourceDBaaSFirewallV1Read(ctx, d, meta) | ||
} | ||
|
||
func resourceDBaaSFirewallV1Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
datastoreID := d.Get("datastore_id").(string) | ||
|
||
dbaasClient, diagErr := getDBaaSClient(d, meta) | ||
if diagErr != nil { | ||
return diagErr | ||
} | ||
|
||
log.Print(msgGet(objectDatastore, datastoreID)) | ||
datastore, err := dbaasClient.Datastore(ctx, datastoreID) | ||
if err != nil { | ||
return diag.FromErr(errGettingObject(objectDatastore, datastoreID, err)) | ||
} | ||
|
||
checksum, err := firewallChecksum(datastore.Firewall, datastoreID) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
d.SetId(checksum) | ||
|
||
return nil | ||
} | ||
|
||
func resourceDBaaSFirewallV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
datastoreID := d.Get("datastore_id").(string) | ||
|
||
dbaasClient, diagErr := getDBaaSClient(d, meta) | ||
if diagErr != nil { | ||
return diagErr | ||
} | ||
|
||
firewallOpts := getEmptyFirewallOpts() | ||
|
||
log.Print(msgUpdate(objectDatastore, datastoreID, firewallOpts)) | ||
_, err := dbaasClient.FirewallDatastore(ctx, datastoreID, firewallOpts) | ||
if err != nil { | ||
return diag.FromErr(errUpdatingObject(objectDatastore, datastoreID, err)) | ||
} | ||
|
||
log.Printf("[DEBUG] waiting for datastore %s to become 'ACTIVE'", datastoreID) | ||
timeout := d.Timeout(schema.TimeoutUpdate) | ||
err = waiters.WaitForDBaaSDatastoreV1ActiveState(ctx, dbaasClient, datastoreID, timeout) | ||
if err != nil { | ||
return diag.FromErr(errUpdatingObject(objectDatastore, datastoreID, err)) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceDBaaSFirewallV1ImportState(_ context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { | ||
config := meta.(*Config) | ||
if config.ProjectID == "" { | ||
return nil, errors.New("SEL_PROJECT_ID must be set for the resource import") | ||
} | ||
if config.Region == "" { | ||
return nil, errors.New("SEL_REGION must be set for the resource import") | ||
} | ||
|
||
d.Set("project_id", config.ProjectID) | ||
d.Set("region", config.Region) | ||
|
||
return []*schema.ResourceData{d}, nil | ||
} | ||
|
||
func getEmptyFirewallOpts() dbaas.DatastoreFirewallOpts { | ||
return dbaas.DatastoreFirewallOpts{IPs: []string{}} | ||
} | ||
|
||
func resourceDBaaSDatastoreV1FirewallOptsFromSet(firewallSet *schema.Set) (dbaas.DatastoreFirewallOpts, error) { | ||
if firewallSet.Len() == 0 { | ||
return getEmptyFirewallOpts(), nil | ||
} | ||
|
||
var resourceIPsRaw interface{} | ||
var ok bool | ||
|
||
resourceFirewallRaw := firewallSet.List()[0].(map[string]interface{}) | ||
if resourceIPsRaw, ok = resourceFirewallRaw["ips"]; !ok { | ||
return dbaas.DatastoreFirewallOpts{}, errors.New("firewall.ips value isn't provided") | ||
} | ||
resourceIPRaw := resourceIPsRaw.([]interface{}) | ||
var firewall dbaas.DatastoreFirewallOpts | ||
for _, ip := range resourceIPRaw { | ||
firewall.IPs = append(firewall.IPs, ip.(string)) | ||
} | ||
|
||
return firewall, nil | ||
} | ||
|
||
func resourceDBaaSDatastoreV1FirewallOptsFromList(rawList []interface{}) (dbaas.DatastoreFirewallOpts, error) { | ||
if len(rawList) == 0 { | ||
return getEmptyFirewallOpts(), nil | ||
} | ||
|
||
ipsList := make([]string, len(rawList)) | ||
for i := range rawList { | ||
ipsList[i] = rawList[i].(string) | ||
} | ||
|
||
var firewall dbaas.DatastoreFirewallOpts | ||
firewall.IPs = append(firewall.IPs, ipsList...) | ||
|
||
return firewall, nil | ||
} | ||
|
||
func firewallChecksum(firewall []dbaas.Firewall, datastoreID string) (string, error) { | ||
ipsList := make([]string, len(firewall)) | ||
for _, rule := range firewall { | ||
ipsList = append(ipsList, rule.IP) | ||
} | ||
|
||
ipsList = append(ipsList, datastoreID) | ||
checksum, err := stringListChecksum(ipsList) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return checksum, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package selectel | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/selectel/go-selvpcclient/v3/selvpcclient/resell/v2/projects" | ||
) | ||
|
||
func TestAccDBaaSFirewallV1Basic(t *testing.T) { | ||
var project projects.Project | ||
|
||
projectName := acctest.RandomWithPrefix("tf-acc") | ||
datastoreName := acctest.RandomWithPrefix("tf-acc-ds") | ||
nodeCount := 1 | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccSelectelPreCheck(t) }, | ||
ProviderFactories: testAccProviders, | ||
CheckDestroy: testAccCheckVPCV2ProjectDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccDBaaSFirewallV1Basic(projectName, datastoreName, nodeCount), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckVPCV2ProjectExists("selectel_vpc_project_v2.project_tf_acc_test_1", &project), | ||
resource.TestCheckResourceAttrSet("selectel_dbaas_firewall_v1.firewall_tf_acc_test_1", "datastore_id"), | ||
resource.TestCheckResourceAttr("selectel_dbaas_firewall_v1.firewall_tf_acc_test_1", "ips.#", "2"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccDBaaSFirewallV1Basic(projectName, datastoreName string, nodeCount int) string { | ||
return fmt.Sprintf(` | ||
resource "selectel_vpc_project_v2" "project_tf_acc_test_1" { | ||
name = "%s" | ||
} | ||
resource "selectel_vpc_subnet_v2" "subnet_tf_acc_test_1" { | ||
project_id = "${selectel_vpc_project_v2.project_tf_acc_test_1.id}" | ||
region = "ru-3" | ||
} | ||
data "selectel_dbaas_datastore_type_v1" "dt" { | ||
project_id = "${selectel_vpc_project_v2.project_tf_acc_test_1.id}" | ||
region = "ru-3" | ||
filter { | ||
engine = "postgresql" | ||
version = "16" | ||
} | ||
} | ||
resource "selectel_dbaas_datastore_v1" "datastore_tf_acc_test_1" { | ||
name = "%s" | ||
project_id = "${selectel_vpc_project_v2.project_tf_acc_test_1.id}" | ||
region = "ru-3" | ||
type_id = "${data.selectel_dbaas_datastore_type_v1.dt.datastore_types[0].id}" | ||
subnet_id = "${selectel_vpc_subnet_v2.subnet_tf_acc_test_1.subnet_id}" | ||
node_count = "%d" | ||
flavor { | ||
vcpus = 2 | ||
ram = 4096 | ||
disk = 32 | ||
} | ||
} | ||
resource "selectel_dbaas_firewall_v1" "firewall_tf_acc_test_1" { | ||
project_id = "${selectel_vpc_project_v2.project_tf_acc_test_1.id}" | ||
region = "ru-3" | ||
datastore_id = "${selectel_dbaas_datastore_v1.datastore_tf_acc_test_1.id}" | ||
ips = [ "127.0.0.1", "127.0.0.2" ] | ||
}`, projectName, datastoreName, nodeCount) | ||
} |
30 changes: 30 additions & 0 deletions
30
selectel/schemas/dbaas/schema_selectel_dbaas_firewall_v1.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package schemas | ||
|
||
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
|
||
func ResourceDBaaSFirewallV1Schema() map[string]*schema.Schema { | ||
return map[string]*schema.Schema{ | ||
"project_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"region": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"datastore_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"ips": { | ||
Type: schema.TypeList, | ||
Required: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.