Skip to content

Commit 6adca90

Browse files
committed
feat(mongodb): resource instance
1 parent 69c8334 commit 6adca90

File tree

10 files changed

+1887
-5
lines changed

10 files changed

+1887
-5
lines changed

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ require (
2929
gopkg.in/dnaeon/go-vcr.v3 v3.2.0
3030
)
3131

32+
replace github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 => /Users/jonathanremy/Desktop/protoc-gen/_generated/scaleway-sdk-go
33+
3234
require (
3335
github.com/Masterminds/goutils v1.1.1 // indirect
3436
github.com/Masterminds/semver/v3 v3.2.0 // indirect
@@ -110,7 +112,7 @@ require (
110112
golang.org/x/net v0.25.0 // indirect
111113
golang.org/x/sync v0.8.0 // indirect
112114
golang.org/x/sys v0.23.0 // indirect
113-
golang.org/x/text v0.17.0 // indirect
115+
golang.org/x/text v0.18.0 // indirect
114116
golang.org/x/time v0.3.0 // indirect
115117
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
116118
google.golang.org/appengine v1.6.8 // indirect

go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,6 @@ github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXq
242242
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
243243
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
244244
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
245-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 h1:yoKAVkEVwAqbGbR8n87rHQ1dulL25rKloGadb3vm770=
246-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30/go.mod h1:sH0u6fq6x4R5M7WxkoQFY/o7UaiItec0o1LinLCJNq8=
247245
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
248246
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
249247
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
@@ -361,8 +359,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
361359
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
362360
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
363361
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
364-
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
365-
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
362+
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
363+
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
366364
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
367365
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
368366
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
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)