Skip to content

Commit 3e7ffa2

Browse files
committed
feat(mongodb): resource instance
1 parent 4204b3a commit 3e7ffa2

File tree

8 files changed

+1882
-0
lines changed

8 files changed

+1882
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package redis
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/scaleway/scaleway-sdk-go/api/redis/v1"
10+
"github.com/scaleway/scaleway-sdk-go/scw"
11+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/datasource"
12+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
13+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
14+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
15+
)
16+
17+
func DataSourceCluster() *schema.Resource {
18+
// Generate datasource schema from resource
19+
dsSchema := datasource.SchemaFromResourceSchema(ResourceCluster().Schema)
20+
// Set 'Optional' schema elements
21+
datasource.AddOptionalFieldsToSchema(dsSchema, "name", "zone", "project_id")
22+
23+
dsSchema["name"].ConflictsWith = []string{"cluster_id"}
24+
dsSchema["cluster_id"] = &schema.Schema{
25+
Type: schema.TypeString,
26+
Optional: true,
27+
Description: "The ID of the Redis cluster",
28+
ConflictsWith: []string{"name"},
29+
ValidateDiagFunc: verify.IsUUIDorUUIDWithLocality(),
30+
}
31+
32+
return &schema.Resource{
33+
ReadContext: DataSourceClusterRead,
34+
Schema: dsSchema,
35+
}
36+
}
37+
38+
func DataSourceClusterRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
39+
api, zone, err := newAPIWithZone(d, m)
40+
if err != nil {
41+
return diag.FromErr(err)
42+
}
43+
44+
clusterID, ok := d.GetOk("cluster_id")
45+
if !ok {
46+
clusterName := d.Get("name").(string)
47+
res, err := api.ListClusters(&redis.ListClustersRequest{
48+
Zone: zone,
49+
Name: types.ExpandStringPtr(clusterName),
50+
ProjectID: types.ExpandStringPtr(d.Get("project_id")),
51+
}, scw.WithContext(ctx))
52+
if err != nil {
53+
return diag.FromErr(err)
54+
}
55+
56+
foundCluster, err := datasource.FindExact(
57+
res.Clusters,
58+
func(s *redis.Cluster) bool { return s.Name == clusterName },
59+
clusterName,
60+
)
61+
if err != nil {
62+
return diag.FromErr(err)
63+
}
64+
65+
clusterID = foundCluster.ID
66+
}
67+
68+
zonedID := datasource.NewZonedID(clusterID, zone)
69+
d.SetId(zonedID)
70+
err = d.Set("cluster_id", zonedID)
71+
if err != nil {
72+
return diag.FromErr(err)
73+
}
74+
75+
// Check if cluster exist as Read will return nil if resource does not exist
76+
// clusterID may be zoned if using name in data source
77+
getReq := &redis.GetClusterRequest{
78+
Zone: zone,
79+
ClusterID: locality.ExpandID(clusterID.(string)),
80+
}
81+
_, err = api.GetCluster(getReq, scw.WithContext(ctx))
82+
if err != nil {
83+
return diag.FromErr(fmt.Errorf("no clusters found with the id %s", clusterID))
84+
}
85+
86+
return ResourceInstanceRead(ctx, d, m)
87+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package redis_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest"
9+
)
10+
11+
func TestAccDataSourceCluster_Basic(t *testing.T) {
12+
tt := acctest.NewTestTools(t)
13+
defer tt.Cleanup()
14+
latestRedisVersion := getLatestVersion(tt)
15+
resource.ParallelTest(t, resource.TestCase{
16+
PreCheck: func() { acctest.PreCheck(t) },
17+
ProviderFactories: tt.ProviderFactories,
18+
CheckDestroy: isClusterDestroyed(tt),
19+
Steps: []resource.TestStep{
20+
{
21+
Config: fmt.Sprintf(`
22+
resource "scaleway_redis_cluster" "test" {
23+
name = "test_redis_datasource_terraform"
24+
version = "%s"
25+
node_type = "RED1-micro"
26+
user_name = "my_initial_user"
27+
password = "thiZ_is_v&ry_s3cret"
28+
}
29+
30+
data "scaleway_redis_cluster" "test" {
31+
name = scaleway_redis_cluster.test.name
32+
}
33+
34+
data "scaleway_redis_cluster" "test2" {
35+
cluster_id = scaleway_redis_cluster.test.id
36+
}
37+
`, latestRedisVersion),
38+
Check: resource.ComposeTestCheckFunc(
39+
isClusterPresent(tt, "scaleway_redis_cluster.test"),
40+
41+
resource.TestCheckResourceAttr("data.scaleway_redis_cluster.test", "name", "test_redis_datasource_terraform"),
42+
resource.TestCheckResourceAttrSet("data.scaleway_redis_cluster.test", "id"),
43+
44+
resource.TestCheckResourceAttr("data.scaleway_redis_cluster.test2", "name", "test_redis_datasource_terraform"),
45+
resource.TestCheckResourceAttrSet("data.scaleway_redis_cluster.test2", "id"),
46+
),
47+
},
48+
},
49+
})
50+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package redis
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"fmt"
7+
"sort"
8+
"time"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
mongodb "github.com/scaleway/scaleway-sdk-go/api/mongodb/v1alpha1"
12+
"github.com/scaleway/scaleway-sdk-go/api/redis/v1"
13+
"github.com/scaleway/scaleway-sdk-go/scw"
14+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
15+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
16+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
17+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/transport"
18+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
19+
)
20+
21+
const (
22+
defaultRedisClusterTimeout = 15 * time.Minute
23+
defaultWaitRedisClusterRetryInterval = 5 * time.Second
24+
)
25+
26+
func newAPI(m interface{}) *mongodb.API {
27+
return mongodb.NewAPI(meta.ExtractScwClient(m))
28+
}
29+
30+
// newAPIWithZone returns a new Redis API and the zone for a Create request
31+
func newAPIWithZone(d *schema.ResourceData, m interface{}) (*mongodb.API, scw.Zone, error) {
32+
zone, err := meta.ExtractZone(d, m)
33+
if err != nil {
34+
return nil, "", err
35+
}
36+
return newAPI(m), zone, nil
37+
}
38+
39+
// NewAPIWithZoneAndID returns a Redis API with zone and ID extracted from the state
40+
func NewAPIWithZoneAndID(m interface{}, id string) (*redis.API, scw.Zone, string, error) {
41+
zone, ID, err := zonal.ParseID(id)
42+
if err != nil {
43+
return nil, "", "", err
44+
}
45+
return newAPI(m), zone, ID, nil
46+
}
47+
48+
func waitForInstance(ctx context.Context, api *mongodb.API, zone scw.Zone, id string, timeout time.Duration) (*redis.Cluster, error) {
49+
retryInterval := defaultWaitRedisClusterRetryInterval
50+
if transport.DefaultWaitRetryInterval != nil {
51+
retryInterval = *transport.DefaultWaitRetryInterval
52+
}
53+
54+
return api.WaitForInstance()
55+
}
56+
57+
func waitForCluster(ctx context.Context, api *redis.API, zone scw.Zone, id string, timeout time.Duration) (*redis.Cluster, error) {
58+
retryInterval := defaultWaitRedisClusterRetryInterval
59+
if transport.DefaultWaitRetryInterval != nil {
60+
retryInterval = *transport.DefaultWaitRetryInterval
61+
}
62+
63+
return api.WaitForCluster(&redis.WaitForClusterRequest{
64+
Zone: zone,
65+
Timeout: scw.TimeDurationPtr(timeout),
66+
ClusterID: id,
67+
RetryInterval: &retryInterval,
68+
}, scw.WithContext(ctx))
69+
}
70+
71+
func privateNetworkSetHash(v interface{}) int {
72+
var buf bytes.Buffer
73+
74+
m := v.(map[string]interface{})
75+
if pnID, ok := m["id"]; ok {
76+
buf.WriteString(locality.ExpandID(pnID))
77+
}
78+
79+
if serviceIPs, ok := m["service_ips"]; ok {
80+
// Sort the service IPs before generating the hash.
81+
ips := serviceIPs.([]interface{})
82+
sort.Slice(ips, func(i, j int) bool {
83+
return ips[i].(string) < ips[j].(string)
84+
})
85+
86+
for i, item := range ips {
87+
buf.WriteString(fmt.Sprintf("%d-%s-", i, item.(string)))
88+
}
89+
}
90+
91+
return types.StringHashcode(buf.String())
92+
}

0 commit comments

Comments
 (0)