Skip to content

Commit 9d23bf4

Browse files
committed
Add base64_encode_content attribute to datasources that may return binary content
This field should workaround v0.12 regression that causes binary content to be corrupted when written directly to state.
1 parent 94ac23f commit 9d23bf4

14 files changed

+134
-17
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- Support for Granular Security Lists using Network Security Group
88
- Support for Granular Security Lists in Load Balancer
99
- Support for Network Security Groups in databases
10+
- Support in autonomous database and object data sources for encoding downloaded binary content as base64. This works around behavior in Terraform v0.12 that could cause binary content to be corrupted if written directly to state.
1011

1112
### Fixed
1213
- Address panics caused by invalid type assertions in object map conversion. This could potentially affect attributes

examples/database/adb/autonomous_data_warehouse_wallet.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ resource "random_string" "autonomous_data_warehouse_wallet_password" {
66
}
77

88
data "oci_database_autonomous_database_wallet" "autonomous_data_warehouse_wallet" {
9-
#Required
109
autonomous_database_id = "${oci_database_autonomous_database.autonomous_data_warehouse.id}"
1110
password = "${random_string.autonomous_data_warehouse_wallet_password.result}"
11+
base64_encode_content = "true"
1212
}
1313

1414
resource "local_file" "autonomous_data_warehouse_wallet_file" {
15-
content = "${data.oci_database_autonomous_database_wallet.autonomous_data_warehouse_wallet.content}"
16-
filename = "${path.module}/autonomous_data_warehouse_wallet.zip"
15+
content_base64 = "${data.oci_database_autonomous_database_wallet.autonomous_data_warehouse_wallet.content}"
16+
filename = "${path.module}/autonomous_data_warehouse_wallet.zip"
1717
}
1818

1919
output "autonomous_data_warehouse_wallet_password" {

examples/database/adb/autonomous_database_wallet.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ resource "random_string" "autonomous_database_wallet_password" {
66
}
77

88
data "oci_database_autonomous_database_wallet" "autonomous_database_wallet" {
9-
#Required
109
autonomous_database_id = "${oci_database_autonomous_database.autonomous_database.id}"
1110
password = "${random_string.autonomous_database_wallet_password.result}"
11+
base64_encode_content = "true"
1212
}
1313

1414
resource "local_file" "autonomous_database_wallet_file" {
15-
content = "${data.oci_database_autonomous_database_wallet.autonomous_database_wallet.content}"
16-
filename = "${path.module}/autonomous_database_wallet.zip"
15+
content_base64 = "${data.oci_database_autonomous_database_wallet.autonomous_database_wallet.content}"
16+
filename = "${path.module}/autonomous_database_wallet.zip"
1717
}
1818

1919
output "autonomous_database_wallet_password" {

examples/database/adb/provider.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ provider "oci" {
77
private_key_path = "${var.private_key_path}"
88
region = "${var.region}"
99
}
10+
11+
provider "local" {
12+
version = ">=1.3.0" # Need this version of the local provider to support base64 encoded inputs
13+
}

oci/database_autonomous_data_warehouse_wallet_data_source.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package provider
44

55
import (
66
"context"
7+
"encoding/base64"
78
"io/ioutil"
89

910
"github.com/hashicorp/terraform/helper/schema"
@@ -24,6 +25,11 @@ func DatabaseAutonomousDataWarehouseWalletDataSource() *schema.Resource {
2425
Required: true,
2526
Sensitive: true,
2627
},
28+
"base64_encode_content": {
29+
Type: schema.TypeBool,
30+
Optional: true,
31+
Default: false,
32+
},
2733

2834
// Computed
2935
"content": {
@@ -91,7 +97,18 @@ func (s *DatabaseAutonomousDataWarehouseWalletDataSourceCrud) SetData() error {
9197

9298
s.D.SetId(GenerateDataSourceID())
9399

94-
s.D.Set("content", string(*s.Res))
100+
base64EncodeContent := false
101+
if tmp, ok := s.D.GetOkExists("base64_encode_content"); ok {
102+
base64EncodeContent = tmp.(bool)
103+
}
104+
105+
if base64EncodeContent {
106+
// This use case is for v0.12, where content should be base64 encoded to avoid
107+
// being normalized before setting in state. Otherwise, the zip file may get corrupted.
108+
s.D.Set("content", base64.StdEncoding.EncodeToString(*s.Res))
109+
} else {
110+
s.D.Set("content", string(*s.Res))
111+
}
95112

96113
return nil
97114
}

oci/database_autonomous_data_warehouse_wallet_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var (
1616
autonomousDataWarehouseWalletSingularDataSourceRepresentation = map[string]interface{}{
1717
"autonomous_data_warehouse_id": Representation{repType: Required, create: `${oci_database_autonomous_data_warehouse.test_autonomous_data_warehouse.id}`},
1818
"password": Representation{repType: Required, create: `BEstrO0ng_#11`},
19+
"base64_encode_content": Representation{repType: Optional, create: `true`},
1920
}
2021

2122
AutonomousDataWarehouseWalletResourceConfig = AutonomousDataWarehouseResourceConfig
@@ -47,9 +48,22 @@ func TestDatabaseAutonomousDataWarehouseWalletResource_basic(t *testing.T) {
4748
Check: resource.ComposeAggregateTestCheckFunc(
4849
resource.TestCheckResourceAttrSet(singularDatasourceName, "autonomous_data_warehouse_id"),
4950
resource.TestCheckResourceAttr(singularDatasourceName, "password", "BEstrO0ng_#11"),
51+
resource.TestCheckResourceAttr(singularDatasourceName, "base64_encode_content", "false"),
5052
resource.TestCheckResourceAttrSet(singularDatasourceName, "content"),
5153
),
5254
},
55+
// verify datasource with base64 encoded content
56+
{
57+
Config: config +
58+
generateDataSourceFromRepresentationMap("oci_database_autonomous_data_warehouse_wallet", "test_autonomous_data_warehouse_wallet", Optional, Create, autonomousDataWarehouseWalletSingularDataSourceRepresentation) +
59+
compartmentIdVariableStr + AutonomousDataWarehouseWalletResourceConfig,
60+
Check: resource.ComposeAggregateTestCheckFunc(
61+
resource.TestCheckResourceAttrSet(singularDatasourceName, "autonomous_data_warehouse_id"),
62+
resource.TestCheckResourceAttr(singularDatasourceName, "password", "BEstrO0ng_#11"),
63+
resource.TestCheckResourceAttr(singularDatasourceName, "base64_encode_content", "true"),
64+
testCheckAttributeBase64Encoded(singularDatasourceName, "content", true),
65+
),
66+
},
5367
},
5468
})
5569
}

oci/database_autonomous_database_wallet_data_source.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package provider
44

55
import (
66
"context"
7+
"encoding/base64"
78
"io/ioutil"
89

910
"github.com/hashicorp/terraform/helper/schema"
@@ -24,6 +25,11 @@ func DatabaseAutonomousDatabaseWalletDataSource() *schema.Resource {
2425
Required: true,
2526
Sensitive: true,
2627
},
28+
"base64_encode_content": {
29+
Type: schema.TypeBool,
30+
Optional: true,
31+
Default: false,
32+
},
2733

2834
// Computed
2935
"content": {
@@ -91,7 +97,18 @@ func (s *DatabaseAutonomousDatabaseWalletDataSourceCrud) SetData() error {
9197

9298
s.D.SetId(GenerateDataSourceID())
9399

94-
s.D.Set("content", string(*s.Res))
100+
base64EncodeContent := false
101+
if tmp, ok := s.D.GetOkExists("base64_encode_content"); ok {
102+
base64EncodeContent = tmp.(bool)
103+
}
104+
105+
if base64EncodeContent {
106+
// This use case is for v0.12, where content should be base64 encoded to avoid
107+
// being normalized before setting in state. Otherwise, the zip file may get corrupted.
108+
s.D.Set("content", base64.StdEncoding.EncodeToString(*s.Res))
109+
} else {
110+
s.D.Set("content", string(*s.Res))
111+
}
95112

96113
return nil
97114
}

oci/database_autonomous_database_wallet_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var (
1616
autonomousDatabaseWalletSingularDataSourceRepresentation = map[string]interface{}{
1717
"autonomous_database_id": Representation{repType: Required, create: `${oci_database_autonomous_database.test_autonomous_database.id}`},
1818
"password": Representation{repType: Required, create: `BEstrO0ng_#11`},
19+
"base64_encode_content": Representation{repType: Optional, create: `true`},
1920
}
2021

2122
AutonomousDatabaseWalletResourceConfig = AutonomousDatabaseResourceConfig
@@ -47,9 +48,22 @@ func TestDatabaseAutonomousDatabaseWalletResource_basic(t *testing.T) {
4748
Check: resource.ComposeAggregateTestCheckFunc(
4849
resource.TestCheckResourceAttrSet(singularDatasourceName, "autonomous_database_id"),
4950
resource.TestCheckResourceAttr(singularDatasourceName, "password", "BEstrO0ng_#11"),
51+
resource.TestCheckResourceAttr(singularDatasourceName, "base64_encode_content", "false"),
5052
resource.TestCheckResourceAttrSet(singularDatasourceName, "content"),
5153
),
5254
},
55+
// verify datasource with base64 encoded content
56+
{
57+
Config: config +
58+
generateDataSourceFromRepresentationMap("oci_database_autonomous_database_wallet", "test_autonomous_database_wallet", Optional, Create, autonomousDatabaseWalletSingularDataSourceRepresentation) +
59+
compartmentIdVariableStr + AutonomousDatabaseWalletResourceConfig,
60+
Check: resource.ComposeAggregateTestCheckFunc(
61+
resource.TestCheckResourceAttrSet(singularDatasourceName, "autonomous_database_id"),
62+
resource.TestCheckResourceAttr(singularDatasourceName, "password", "BEstrO0ng_#11"),
63+
resource.TestCheckResourceAttr(singularDatasourceName, "base64_encode_content", "true"),
64+
testCheckAttributeBase64Encoded(singularDatasourceName, "content", true),
65+
),
66+
},
5367
},
5468
})
5569
}

oci/object_storage_object_data_source.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package provider
44

55
import (
66
"context"
7+
"encoding/base64"
78
"fmt"
89
"io/ioutil"
910
"log"
@@ -35,6 +36,11 @@ func ObjectStorageObjectDataSource() *schema.Resource {
3536
//default value is 1MB
3637
Default: 1048576,
3738
},
39+
"base64_encode_content": {
40+
Type: schema.TypeBool,
41+
Optional: true,
42+
Default: false,
43+
},
3844

3945
// Computed
4046
"content": {
@@ -144,10 +150,19 @@ func (s *ObjectStorageObjectDataSourceCrud) SetData() error {
144150

145151
s.D.SetId(GenerateDataSourceID())
146152

153+
base64EncodeContent := false
154+
if tmp, ok := s.D.GetOkExists("base64_encode_content"); ok {
155+
base64EncodeContent = tmp.(bool)
156+
}
157+
147158
contentReader := s.Res.Content
148159
contentArray, err := ioutil.ReadAll(contentReader)
149160
if err != nil {
150161
log.Printf("unable to read 'content' from response. Error: %v", err)
162+
} else if base64EncodeContent {
163+
// This use case is for v0.12, where content should be base64 encoded to avoid
164+
// being normalized before setting in state.
165+
s.D.Set("content", base64.StdEncoding.EncodeToString(contentArray))
151166
} else {
152167
s.D.Set("content", string(contentArray))
153168
}

oci/object_storage_object_test.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package provider
55
import (
66
"context"
77
"crypto/md5"
8+
"encoding/base64"
89
"encoding/hex"
910
"fmt"
1011
"io/ioutil"
@@ -42,10 +43,11 @@ var (
4243
}
4344

4445
objectSingularDataSourceRepresentation = map[string]interface{}{
45-
"bucket": Representation{repType: Required, create: `${oci_objectstorage_bucket.test_bucket.name}`},
46-
"namespace": Representation{repType: Required, create: `${oci_objectstorage_bucket.test_bucket.namespace}`},
47-
"object": Representation{repType: Required, create: `my-test-object-3`},
48-
"content_length_limit": Representation{repType: Optional, create: `17`, update: `15`},
46+
"bucket": Representation{repType: Required, create: `${oci_objectstorage_bucket.test_bucket.name}`},
47+
"namespace": Representation{repType: Required, create: `${oci_objectstorage_bucket.test_bucket.namespace}`},
48+
"object": Representation{repType: Required, create: `my-test-object-3`},
49+
"content_length_limit": Representation{repType: Optional, create: `17`, update: `15`},
50+
"base64_encode_content": Representation{repType: Optional, create: `true`},
4951
}
5052

5153
objectRepresentation = map[string]interface{}{
@@ -204,6 +206,7 @@ func TestObjectStorageObjectResource_basic(t *testing.T) {
204206
getUpdatedRepresentationCopy("object", Representation{repType: Required, create: `my-test-object-1`, update: `my-test-object-3`}, objectRepresentation)) +
205207
generateDataSourceFromRepresentationMap("oci_objectstorage_object", "test_object", Required, Create, objectSingularDataSourceRepresentation),
206208
Check: resource.ComposeAggregateTestCheckFunc(
209+
resource.TestCheckResourceAttr(singularDatasourceName, "base64_encode_content", "false"),
207210
resource.TestCheckResourceAttr(singularDatasourceName, "content_encoding", "identity"),
208211
resource.TestCheckResourceAttr(singularDatasourceName, "content_language", "en-CA"),
209212
resource.TestCheckResourceAttr(singularDatasourceName, "content_length", "16"),
@@ -218,20 +221,22 @@ func TestObjectStorageObjectResource_basic(t *testing.T) {
218221
resource.TestCheckResourceAttr(singularDatasourceName, "object", "my-test-object-3"),
219222
),
220223
},
224+
// verify base64 encoding in singular datasource
221225
{
222226
Config: config + compartmentIdVariableStr + ObjectResourceDependencies +
223227
generateResourceFromRepresentationMap("oci_objectstorage_object", "test_object", Optional, Update,
224228
getUpdatedRepresentationCopy("object", Representation{repType: Required, create: `my-test-object-1`, update: `my-test-object-3`}, objectRepresentation)) +
225229
generateDataSourceFromRepresentationMap("oci_objectstorage_object", "test_object", Optional, Create, objectSingularDataSourceRepresentation),
226230
Check: resource.ComposeAggregateTestCheckFunc(
231+
resource.TestCheckResourceAttr(singularDatasourceName, "base64_encode_content", "true"),
227232
resource.TestCheckResourceAttr(singularDatasourceName, "content_encoding", "identity"),
228233
resource.TestCheckResourceAttr(singularDatasourceName, "content_language", "en-CA"),
229234
resource.TestCheckResourceAttr(singularDatasourceName, "content_length", "16"),
230235
resource.TestCheckResourceAttrSet(singularDatasourceName, "content_md5"),
231236
resource.TestCheckResourceAttr(singularDatasourceName, "content_type", "text/xml"),
232237
resource.TestCheckResourceAttr(singularDatasourceName, "bucket", testBucketName),
233238
resource.TestCheckResourceAttrSet(singularDatasourceName, "content"),
234-
resource.TestCheckResourceAttr(singularDatasourceName, "content", "<a1>content</a1>"),
239+
resource.TestCheckResourceAttr(singularDatasourceName, "content", base64.StdEncoding.EncodeToString([]byte("<a1>content</a1>"))),
235240
resource.TestCheckResourceAttr(singularDatasourceName, "metadata.%", "1"),
236241
resource.TestCheckResourceAttr(singularDatasourceName, "metadata.content-type", "text/xml"),
237242
resource.TestCheckResourceAttrSet(singularDatasourceName, "namespace"),

0 commit comments

Comments
 (0)