Skip to content

Commit 9b310fc

Browse files
Feroz Shaikhravinitp
authored andcommitted
Added - Support for MHS Persistent read load balancer endpoint
1 parent 9874005 commit 9b310fc

13 files changed

+383
-1
lines changed

examples/mysql/main.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ resource "oci_mysql_mysql_db_system" "test_mysql_db_system" {
8989
window_start_time = "01:00-00:00"
9090
}
9191

92+
#Optional
93+
read_endpoint {
94+
is_enabled = "false"
95+
}
96+
9297
#defined_tags = {"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}" = "${var.mysql_defined_tags_value}"}
9398
#freeform_tags = var.mysql_freeform_tags
9499
description = "MySQL Database Service"
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
2+
// Licensed under the Mozilla Public License v2.0
3+
4+
package integrationtest
5+
6+
import (
7+
"fmt"
8+
"testing"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
12+
13+
"github.com/oracle/terraform-provider-oci/httpreplay"
14+
"github.com/oracle/terraform-provider-oci/internal/acctest"
15+
"github.com/oracle/terraform-provider-oci/internal/utils"
16+
)
17+
18+
var (
19+
MysqlMysqlDbSystemRepresentationWithReadEndpoint = map[string]interface{}{
20+
"admin_password": acctest.Representation{RepType: acctest.Required, Create: `BEstrO0ng_#11`},
21+
"admin_username": acctest.Representation{RepType: acctest.Required, Create: `adminUser`},
22+
"availability_domain": acctest.Representation{RepType: acctest.Required, Create: `${data.oci_identity_availability_domains.test_availability_domains.availability_domains.0.name}`},
23+
"compartment_id": acctest.Representation{RepType: acctest.Required, Create: `${var.compartment_id}`},
24+
"shape_name": acctest.Representation{RepType: acctest.Required, Create: `MySQL.VM.Standard3.4.64GB`},
25+
"subnet_id": acctest.Representation{RepType: acctest.Required, Create: `${oci_core_subnet.test_subnet.id}`},
26+
"data_storage_size_in_gb": acctest.Representation{RepType: acctest.Required, Create: `50`},
27+
"database_management": acctest.Representation{RepType: acctest.Optional, Create: `DISABLED`},
28+
"backup_policy": acctest.RepresentationGroup{RepType: acctest.Optional, Group: MysqlMysqlDbSystemBackupPolicyDisabledRepresentation},
29+
"read_endpoint": acctest.RepresentationGroup{RepType: acctest.Optional, Group: MysqlMysqlDbSystemReadEndpointRepresentationForUpdate},
30+
"lifecycle": acctest.RepresentationGroup{RepType: acctest.Optional, Group: ignoreMysqlMysqlDbSystemDefinedTagsChangesRepresentation},
31+
}
32+
33+
ignoreMysqlMysqlDbSystemDefinedTagsChangesRepresentation = map[string]interface{}{
34+
"ignore_changes": acctest.Representation{RepType: acctest.Optional, Create: []string{`defined_tags`}},
35+
}
36+
37+
MysqlMysqlDbSystemReadEndpointRepresentationForUpdate = map[string]interface{}{
38+
"is_enabled": acctest.Representation{RepType: acctest.Optional, Create: `true`, Update: `false`},
39+
}
40+
41+
MysqlMysqlDbSystemBackupPolicyDisabledRepresentation = map[string]interface{}{
42+
"is_enabled": acctest.Representation{RepType: acctest.Optional, Create: `false`},
43+
}
44+
)
45+
46+
// issue-routing-tag: mysql/default
47+
func TestMysqlMysqlDbSystemResource_readEndpointTest(t *testing.T) {
48+
httpreplay.SetScenario("TestMysqlMysqlDbSystemResource_readEndpointTest")
49+
defer httpreplay.SaveScenario()
50+
51+
config := acctest.ProviderTestConfig()
52+
53+
compartmentId := utils.GetEnvSettingWithBlankDefault("compartment_ocid")
54+
compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)
55+
56+
resourceName := "oci_mysql_mysql_db_system.test_mysql_db_system"
57+
58+
var resId, resId2 string
59+
60+
acctest.ResourceTest(t, nil, []resource.TestStep{
61+
// verify Create with read endpoint
62+
{
63+
Config: config + compartmentIdVariableStr + MysqlMysqlDbSystemResourceDependencies +
64+
acctest.GenerateResourceFromRepresentationMap("oci_mysql_mysql_db_system", "test_mysql_db_system", acctest.Optional, acctest.Create, MysqlMysqlDbSystemRepresentationWithReadEndpoint),
65+
Check: acctest.ComposeAggregateTestCheckFuncWrapper(
66+
resource.TestCheckResourceAttr(resourceName, "read_endpoint.#", "1"),
67+
resource.TestCheckResourceAttr(resourceName, "read_endpoint.0.is_enabled", "true"),
68+
69+
func(s *terraform.State) (err error) {
70+
resId, err = acctest.FromInstanceState(s, resourceName, "id")
71+
return err
72+
},
73+
),
74+
},
75+
76+
// verify updates to read endpoint
77+
{
78+
Config: config + compartmentIdVariableStr + MysqlMysqlDbSystemResourceDependencies +
79+
acctest.GenerateResourceFromRepresentationMap("oci_mysql_mysql_db_system", "test_mysql_db_system", acctest.Optional, acctest.Update, MysqlMysqlDbSystemRepresentationWithReadEndpoint),
80+
Check: acctest.ComposeAggregateTestCheckFuncWrapper(
81+
resource.TestCheckResourceAttr(resourceName, "read_endpoint.#", "1"),
82+
resource.TestCheckResourceAttr(resourceName, "read_endpoint.0.is_enabled", "false"),
83+
84+
func(s *terraform.State) (err error) {
85+
resId2, err = acctest.FromInstanceState(s, resourceName, "id")
86+
if resId != resId2 {
87+
return fmt.Errorf("Resource recreated when it was supposed to be updated.")
88+
}
89+
return err
90+
},
91+
),
92+
},
93+
})
94+
}

internal/integrationtest/mysql_mysql_db_system_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ var (
7676
"port_x": acctest.Representation{RepType: acctest.Optional, Create: `33306`},
7777
"secure_connections": acctest.RepresentationGroup{RepType: acctest.Optional, Group: MysqlMysqlDbSystemSecureConnectionsRepresentation},
7878
"lifecycle": acctest.RepresentationGroup{RepType: acctest.Required, Group: ignoreDefinedTagsChangesForMysqlRepBasic},
79+
"read_endpoint": acctest.RepresentationGroup{RepType: acctest.Optional, Group: MysqlMysqlDbSystemReadEndpointRepresentation},
7980
}
8081

8182
ignoreDefinedTagsChangesForMysqlRepBasic = map[string]interface{}{
@@ -121,6 +122,10 @@ var (
121122
"window_start_time": acctest.Representation{RepType: acctest.Required, Create: `sun 01:00`},
122123
}
123124

125+
MysqlMysqlDbSystemReadEndpointRepresentation = map[string]interface{}{
126+
"is_enabled": acctest.Representation{RepType: acctest.Optional, Create: `false`},
127+
}
128+
124129
MysqlMysqlDbSystemSecureConnectionsRepresentation = map[string]interface{}{
125130
"certificate_generation_type": acctest.Representation{RepType: acctest.Required, Create: `SYSTEM`},
126131
}
@@ -214,6 +219,8 @@ func TestMysqlMysqlDbSystemResource_basic(t *testing.T) {
214219
resource.TestCheckResourceAttr(resourceName, "maintenance.0.window_start_time", "sun 01:00"),
215220
resource.TestCheckResourceAttr(resourceName, "port", "3306"),
216221
resource.TestCheckResourceAttr(resourceName, "port_x", "33306"),
222+
resource.TestCheckResourceAttr(resourceName, "read_endpoint.#", "1"),
223+
resource.TestCheckResourceAttr(resourceName, "read_endpoint.0.is_enabled", "false"),
217224
resource.TestCheckResourceAttr(resourceName, "secure_connections.#", "1"),
218225
resource.TestCheckResourceAttr(resourceName, "secure_connections.0.certificate_generation_type", "SYSTEM"),
219226
resource.TestCheckResourceAttrSet(resourceName, "shape_name"),
@@ -387,6 +394,8 @@ func TestMysqlMysqlDbSystemResource_basic(t *testing.T) {
387394
resource.TestCheckResourceAttrSet(singularDatasourceName, "mysql_version"),
388395
resource.TestCheckResourceAttr(singularDatasourceName, "port", "3306"),
389396
resource.TestCheckResourceAttr(singularDatasourceName, "port_x", "33306"),
397+
resource.TestCheckResourceAttr(singularDatasourceName, "read_endpoint.#", "1"),
398+
resource.TestCheckResourceAttr(singularDatasourceName, "read_endpoint.0.is_enabled", "false"),
390399
resource.TestCheckResourceAttr(singularDatasourceName, "secure_connections.#", "1"),
391400
resource.TestCheckResourceAttr(singularDatasourceName, "secure_connections.0.certificate_generation_type", "SYSTEM"),
392401
resource.TestCheckResourceAttr(singularDatasourceName, "source.#", "1"),

internal/service/mysql/mysql_mysql_backup_resource.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,38 @@ func MysqlMysqlBackupResource() *schema.Resource {
384384
Type: schema.TypeInt,
385385
Computed: true,
386386
},
387+
"read_endpoint": {
388+
Type: schema.TypeList,
389+
Computed: true,
390+
Elem: &schema.Resource{
391+
Schema: map[string]*schema.Schema{
392+
// Required
393+
394+
// Optional
395+
396+
// Computed
397+
"exclude_ips": {
398+
Type: schema.TypeList,
399+
Computed: true,
400+
Elem: &schema.Schema{
401+
Type: schema.TypeString,
402+
},
403+
},
404+
"is_enabled": {
405+
Type: schema.TypeBool,
406+
Computed: true,
407+
},
408+
"read_endpoint_hostname_label": {
409+
Type: schema.TypeString,
410+
Computed: true,
411+
},
412+
"read_endpoint_ip_address": {
413+
Type: schema.TypeString,
414+
Computed: true,
415+
},
416+
},
417+
},
418+
},
387419
"region": {
388420
Type: schema.TypeString,
389421
Computed: true,
@@ -1019,6 +1051,10 @@ func DbSystemSnapshotToMap(obj *oci_mysql.DbSystemSnapshot) map[string]interface
10191051
result["port_x"] = int(*obj.PortX)
10201052
}
10211053

1054+
if obj.ReadEndpoint != nil {
1055+
result["read_endpoint"] = []interface{}{ReadEndpointDetailsToMap(obj.ReadEndpoint)}
1056+
}
1057+
10221058
if obj.Region != nil {
10231059
result["region"] = string(*obj.Region)
10241060
}

internal/service/mysql/mysql_mysql_db_system_data_source.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@ func (s *MysqlMysqlDbSystemDataSourceCrud) SetData() error {
196196
s.D.Set("port_x", *s.Res.PortX)
197197
}
198198

199+
if s.Res.ReadEndpoint != nil {
200+
s.D.Set("read_endpoint", []interface{}{ReadEndpointDetailsToMap(s.Res.ReadEndpoint)})
201+
} else {
202+
s.D.Set("read_endpoint", nil)
203+
}
204+
199205
if s.Res.SecureConnections != nil {
200206
s.D.Set("secure_connections", []interface{}{SecureConnectionDetailsToMap(s.Res.SecureConnections)})
201207
} else {

internal/service/mysql/mysql_mysql_db_system_resource.go

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,45 @@ func MysqlMysqlDbSystemResource() *schema.Resource {
321321
Computed: true,
322322
ForceNew: true,
323323
},
324+
"read_endpoint": {
325+
Type: schema.TypeList,
326+
Optional: true,
327+
Computed: true,
328+
MaxItems: 1,
329+
MinItems: 1,
330+
Elem: &schema.Resource{
331+
Schema: map[string]*schema.Schema{
332+
// Required
333+
334+
// Optional
335+
"exclude_ips": {
336+
Type: schema.TypeList,
337+
Optional: true,
338+
Computed: true,
339+
Elem: &schema.Schema{
340+
Type: schema.TypeString,
341+
},
342+
},
343+
"is_enabled": {
344+
Type: schema.TypeBool,
345+
Optional: true,
346+
Computed: true,
347+
},
348+
"read_endpoint_hostname_label": {
349+
Type: schema.TypeString,
350+
Optional: true,
351+
Computed: true,
352+
},
353+
"read_endpoint_ip_address": {
354+
Type: schema.TypeString,
355+
Optional: true,
356+
Computed: true,
357+
},
358+
359+
// Computed
360+
},
361+
},
362+
},
324363
"secure_connections": {
325364
Type: schema.TypeList,
326365
Optional: true,
@@ -1063,6 +1102,17 @@ func (s *MysqlMysqlDbSystemResourceCrud) Create() error {
10631102
request.PortX = &tmp
10641103
}
10651104

1105+
if readEndpoint, ok := s.D.GetOkExists("read_endpoint"); ok {
1106+
if tmpList := readEndpoint.([]interface{}); len(tmpList) > 0 {
1107+
fieldKeyFormat := fmt.Sprintf("%s.%d.%%s", "read_endpoint", 0)
1108+
tmp, err := s.mapToCreateReadEndpointDetails(fieldKeyFormat)
1109+
if err != nil {
1110+
return err
1111+
}
1112+
request.ReadEndpoint = &tmp
1113+
}
1114+
}
1115+
10661116
if secureConnections, ok := s.D.GetOkExists("secure_connections"); ok {
10671117
if tmpList := secureConnections.([]interface{}); len(tmpList) > 0 {
10681118
fieldKeyFormat := fmt.Sprintf("%s.%d.%%s", "secure_connections", 0)
@@ -1244,6 +1294,17 @@ func (s *MysqlMysqlDbSystemResourceCrud) Update() error {
12441294
}
12451295
}
12461296

1297+
if readEndpoint, ok := s.D.GetOkExists("read_endpoint"); ok && s.D.HasChange("read_endpoint") {
1298+
if tmpList := readEndpoint.([]interface{}); len(tmpList) > 0 {
1299+
fieldKeyFormat := fmt.Sprintf("%s.%d.%%s", "read_endpoint", 0)
1300+
tmp, err := s.mapToUpdateReadEndpointDetails(fieldKeyFormat)
1301+
if err != nil {
1302+
return err
1303+
}
1304+
request.ReadEndpoint = &tmp
1305+
}
1306+
}
1307+
12471308
if secureConnections, ok := s.D.GetOkExists("secure_connections"); ok && s.D.HasChange("secure_connections") {
12481309
if tmpList := secureConnections.([]interface{}); len(tmpList) > 0 {
12491310
fieldKeyFormat := fmt.Sprintf("%s.%d.%%s", "secure_connections", 0)
@@ -1413,6 +1474,12 @@ func (s *MysqlMysqlDbSystemResourceCrud) SetData() error {
14131474
s.D.Set("port_x", *s.Res.PortX)
14141475
}
14151476

1477+
if s.Res.ReadEndpoint != nil {
1478+
s.D.Set("read_endpoint", []interface{}{ReadEndpointDetailsToMap(s.Res.ReadEndpoint)})
1479+
} else {
1480+
s.D.Set("read_endpoint", nil)
1481+
}
1482+
14161483
if s.Res.SecureConnections != nil {
14171484
s.D.Set("secure_connections", []interface{}{SecureConnectionDetailsToMap(s.Res.SecureConnections)})
14181485
} else {
@@ -1979,6 +2046,94 @@ func DataStorageToMap(obj *oci_mysql.DataStorage) map[string]interface{} {
19792046
return result
19802047
}
19812048

2049+
func (s *MysqlMysqlDbSystemResourceCrud) mapToCreateReadEndpointDetails(fieldKeyFormat string) (oci_mysql.CreateReadEndpointDetails, error) {
2050+
result := oci_mysql.CreateReadEndpointDetails{}
2051+
2052+
if excludeIps, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "exclude_ips")); ok {
2053+
interfaces := excludeIps.([]interface{})
2054+
tmp := make([]string, len(interfaces))
2055+
for i := range interfaces {
2056+
if interfaces[i] != nil {
2057+
tmp[i] = interfaces[i].(string)
2058+
}
2059+
}
2060+
if len(tmp) != 0 || s.D.HasChange(fmt.Sprintf(fieldKeyFormat, "exclude_ips")) {
2061+
result.ExcludeIps = tmp
2062+
}
2063+
}
2064+
2065+
if isEnabled, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "is_enabled")); ok {
2066+
tmp := isEnabled.(bool)
2067+
result.IsEnabled = &tmp
2068+
}
2069+
2070+
if readEndpointHostnameLabel, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "read_endpoint_hostname_label")); ok {
2071+
tmp := readEndpointHostnameLabel.(string)
2072+
result.ReadEndpointHostnameLabel = &tmp
2073+
}
2074+
2075+
if readEndpointIpAddress, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "read_endpoint_ip_address")); ok {
2076+
tmp := readEndpointIpAddress.(string)
2077+
result.ReadEndpointIpAddress = &tmp
2078+
}
2079+
2080+
return result, nil
2081+
}
2082+
2083+
func (s *MysqlMysqlDbSystemResourceCrud) mapToUpdateReadEndpointDetails(fieldKeyFormat string) (oci_mysql.UpdateReadEndpointDetails, error) {
2084+
result := oci_mysql.UpdateReadEndpointDetails{}
2085+
2086+
if excludeIps, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "exclude_ips")); ok {
2087+
interfaces := excludeIps.([]interface{})
2088+
tmp := make([]string, len(interfaces))
2089+
for i := range interfaces {
2090+
if interfaces[i] != nil {
2091+
tmp[i] = interfaces[i].(string)
2092+
}
2093+
}
2094+
if len(tmp) != 0 || s.D.HasChange(fmt.Sprintf(fieldKeyFormat, "exclude_ips")) {
2095+
result.ExcludeIps = tmp
2096+
}
2097+
}
2098+
2099+
if isEnabled, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "is_enabled")); ok {
2100+
tmp := isEnabled.(bool)
2101+
result.IsEnabled = &tmp
2102+
}
2103+
2104+
if readEndpointHostnameLabel, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "read_endpoint_hostname_label")); ok {
2105+
tmp := readEndpointHostnameLabel.(string)
2106+
result.ReadEndpointHostnameLabel = &tmp
2107+
}
2108+
2109+
if readEndpointIpAddress, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "read_endpoint_ip_address")); ok {
2110+
tmp := readEndpointIpAddress.(string)
2111+
result.ReadEndpointIpAddress = &tmp
2112+
}
2113+
2114+
return result, nil
2115+
}
2116+
2117+
func ReadEndpointDetailsToMap(obj *oci_mysql.ReadEndpointDetails) map[string]interface{} {
2118+
result := map[string]interface{}{}
2119+
2120+
result["exclude_ips"] = obj.ExcludeIps
2121+
2122+
if obj.IsEnabled != nil {
2123+
result["is_enabled"] = bool(*obj.IsEnabled)
2124+
}
2125+
2126+
if obj.ReadEndpointHostnameLabel != nil {
2127+
result["read_endpoint_hostname_label"] = string(*obj.ReadEndpointHostnameLabel)
2128+
}
2129+
2130+
if obj.ReadEndpointIpAddress != nil {
2131+
result["read_endpoint_ip_address"] = string(*obj.ReadEndpointIpAddress)
2132+
}
2133+
2134+
return result
2135+
}
2136+
19822137
func (s *MysqlMysqlDbSystemResourceCrud) mapToCustomerContact(fieldKeyFormat string) (oci_mysql.CustomerContact, error) {
19832138
result := oci_mysql.CustomerContact{}
19842139

0 commit comments

Comments
 (0)