Skip to content

Commit 5aa34ab

Browse files
Add support for database retention in Cloud Composer (#12565) (#20769)
[upstream:7c7f625529fc0cfac7e8ac687428172f52a019d2] Signed-off-by: Modular Magician <[email protected]>
1 parent b4e566d commit 5aa34ab

File tree

3 files changed

+154
-1
lines changed

3 files changed

+154
-1
lines changed

.changelog/12565.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
composer: added `airflow_metadata_retention_config` field to `composer_environment`
3+
```

google/services/composer/resource_composer_environment.go

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ func ResourceComposerEnvironment() *schema.Resource {
706706
"task_logs_retention_config": {
707707
Type: schema.TypeList,
708708
Description: `Optional. The configuration setting for Task Logs.`,
709-
Required: true,
709+
Optional: true,
710710
Elem: &schema.Resource{
711711
Schema: map[string]*schema.Schema{
712712
"storage_mode": {
@@ -718,6 +718,30 @@ func ResourceComposerEnvironment() *schema.Resource {
718718
},
719719
},
720720
},
721+
"airflow_metadata_retention_config": {
722+
Type: schema.TypeList,
723+
Description: `Optional. The configuration setting for database retention.`,
724+
Optional: true,
725+
Computed: true,
726+
Elem: &schema.Resource{
727+
Schema: map[string]*schema.Schema{
728+
"retention_mode": {
729+
Type: schema.TypeString,
730+
Optional: true,
731+
Computed: true,
732+
ValidateFunc: validation.StringInSlice([]string{"RETENTION_MODE_ENABLED", "RETENTION_MODE_DISABLED"}, false),
733+
Description: `Whether database retention is enabled or not. This field is supported for Cloud Composer environments in composer 3 and newer.`,
734+
},
735+
"retention_days": {
736+
Type: schema.TypeInt,
737+
Optional: true,
738+
Computed: true,
739+
ValidateFunc: validation.IntBetween(30, 730),
740+
Description: `How many days data should be retained for. This field is supported for Cloud Composer environments in composer 3 and newer.`,
741+
},
742+
},
743+
},
744+
},
721745
},
722746
},
723747
},
@@ -1470,6 +1494,22 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{})
14701494
return err
14711495
}
14721496
}
1497+
if d.HasChange("config.0.data_retention_config.0.airflow_metadata_retention_config") {
1498+
patchObj := &composer.Environment{
1499+
Config: &composer.EnvironmentConfig{
1500+
DataRetentionConfig: &composer.DataRetentionConfig{
1501+
AirflowMetadataRetentionConfig: &composer.AirflowMetadataRetentionPolicyConfig{},
1502+
},
1503+
},
1504+
}
1505+
if config != nil && config.DataRetentionConfig != nil && config.DataRetentionConfig.AirflowMetadataRetentionConfig != nil {
1506+
patchObj.Config.DataRetentionConfig.AirflowMetadataRetentionConfig = config.DataRetentionConfig.AirflowMetadataRetentionConfig
1507+
}
1508+
err = resourceComposerEnvironmentPatchField("config.DataRetentionConfig.AirflowMetadataRetentionConfig", userAgent, patchObj, d, tfConfig)
1509+
if err != nil {
1510+
return err
1511+
}
1512+
}
14731513
if d.HasChange("config.0.recovery_config.0.scheduled_snapshots_config") {
14741514
patchObj := &composer.Environment{Config: &composer.EnvironmentConfig{}}
14751515
if config != nil {
@@ -1766,6 +1806,7 @@ func flattenComposerEnvironmentConfigDataRetentionConfig(dataRetentionConfig *co
17661806

17671807
transformed := make(map[string]interface{})
17681808
transformed["task_logs_retention_config"] = flattenComposerEnvironmentConfigDataRetentionConfigTaskLogsRetentionConfig(dataRetentionConfig.TaskLogsRetentionConfig)
1809+
transformed["airflow_metadata_retention_config"] = flattenComposerEnvironmentConfigDataRetentionConfigAirflowMetadataRetentionConfig(dataRetentionConfig.AirflowMetadataRetentionConfig)
17691810

17701811
return []interface{}{transformed}
17711812
}
@@ -1781,6 +1822,18 @@ func flattenComposerEnvironmentConfigDataRetentionConfigTaskLogsRetentionConfig(
17811822
return []interface{}{transformed}
17821823
}
17831824

1825+
func flattenComposerEnvironmentConfigDataRetentionConfigAirflowMetadataRetentionConfig(airflowMetadataRetentionConfig *composer.AirflowMetadataRetentionPolicyConfig) interface{} {
1826+
if airflowMetadataRetentionConfig == nil {
1827+
return nil
1828+
}
1829+
1830+
transformed := make(map[string]interface{})
1831+
transformed["retention_mode"] = airflowMetadataRetentionConfig.RetentionMode
1832+
transformed["retention_days"] = airflowMetadataRetentionConfig.RetentionDays
1833+
1834+
return []interface{}{transformed}
1835+
}
1836+
17841837
func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.WorkloadsConfig) interface{} {
17851838
if workloadsConfig == nil {
17861839
return nil
@@ -2249,6 +2302,13 @@ func expandComposerEnvironmentConfigDataRetentionConfig(v interface{}, d *schema
22492302
}
22502303
transformed.TaskLogsRetentionConfig = transformedTaskLogsRetentionConfig
22512304
}
2305+
if airflowMetadataRetentionConfig, ok := original["airflow_metadata_retention_config"]; ok {
2306+
transformedAirflowMetadataRetentionConfig, err := expandComposerEnvironmentConfigDataRetentionConfigAirflowMetadataRetentionConfig(airflowMetadataRetentionConfig, d, config)
2307+
if err != nil {
2308+
return nil, err
2309+
}
2310+
transformed.AirflowMetadataRetentionConfig = transformedAirflowMetadataRetentionConfig
2311+
}
22522312

22532313
return transformed, nil
22542314
}
@@ -2269,6 +2329,25 @@ func expandComposerEnvironmentConfigDataRetentionConfigTaskLogsRetentionConfig(v
22692329
return transformed, nil
22702330
}
22712331

2332+
func expandComposerEnvironmentConfigDataRetentionConfigAirflowMetadataRetentionConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) (*composer.AirflowMetadataRetentionPolicyConfig, error) {
2333+
l := v.([]interface{})
2334+
if len(l) == 0 {
2335+
return nil, nil
2336+
}
2337+
raw := l[0]
2338+
original := raw.(map[string]interface{})
2339+
transformed := &composer.AirflowMetadataRetentionPolicyConfig{}
2340+
2341+
if v, ok := original["retention_mode"]; ok {
2342+
transformed.RetentionMode = v.(string)
2343+
}
2344+
if v, ok := original["retention_days"]; ok {
2345+
transformed.RetentionDays = int64(v.(int))
2346+
}
2347+
2348+
return transformed, nil
2349+
}
2350+
22722351
func expandComposerEnvironmentConfigWorkloadsConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) (*composer.WorkloadsConfig, error) {
22732352
l := v.([]interface{})
22742353
if len(l) == 0 {

google/services/composer/resource_composer_environment_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,39 @@ func TestAccComposerEnvironmentComposer3_withNetworkSubnetworkAndAttachment_expe
11741174
})
11751175
}
11761176

1177+
func TestAccComposerEnvironmentComposer3_databaseRetention(t *testing.T) {
1178+
t.Parallel()
1179+
1180+
envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t))
1181+
network := fmt.Sprintf("%s-%d", testComposerNetworkPrefix, acctest.RandInt(t))
1182+
subnetwork := network + "-1"
1183+
1184+
acctest.VcrTest(t, resource.TestCase{
1185+
PreCheck: func() { acctest.AccTestPreCheck(t) },
1186+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
1187+
CheckDestroy: testAccComposerEnvironmentDestroyProducer(t),
1188+
Steps: []resource.TestStep{
1189+
{
1190+
Config: testAccComposerEnvironmentComposer3_databaseRetention(envName, network, subnetwork),
1191+
},
1192+
{
1193+
ResourceName: "google_composer_environment.test",
1194+
ImportState: true,
1195+
ImportStateVerify: true,
1196+
},
1197+
// This is a terrible clean-up step in order to get destroy to succeed,
1198+
// due to dangling firewall rules left by the Composer Environment blocking network deletion.
1199+
// TODO: Remove this check if firewall rules bug gets fixed by Composer.
1200+
{
1201+
PlanOnly: true,
1202+
ExpectNonEmptyPlan: false,
1203+
Config: testAccComposerEnvironmentComposer3_databaseRetention(envName, network, subnetwork),
1204+
Check: testAccCheckClearComposerEnvironmentFirewalls(t, network),
1205+
},
1206+
},
1207+
})
1208+
}
1209+
11771210
func TestAccComposerEnvironmentComposer3_withNetworkAttachment(t *testing.T) {
11781211
t.Parallel()
11791212

@@ -3246,6 +3279,44 @@ resource "google_compute_subnetwork" "test" {
32463279
`, name, networkAttachment, network, subnetwork)
32473280
}
32483281

3282+
func testAccComposerEnvironmentComposer3_databaseRetention(name, network, subnetwork string) string {
3283+
return fmt.Sprintf(`
3284+
resource "google_composer_environment" "test" {
3285+
name = "%s"
3286+
region = "us-central1"
3287+
config {
3288+
software_config {
3289+
image_version = "composer-3-airflow-2"
3290+
}
3291+
node_config {
3292+
network = google_compute_network.test.id
3293+
subnetwork = google_compute_subnetwork.test.id
3294+
}
3295+
data_retention_config {
3296+
airflow_metadata_retention_config {
3297+
retention_mode = "RETENTION_MODE_ENABLED"
3298+
retention_days = 61
3299+
}
3300+
}
3301+
}
3302+
}
3303+
3304+
// use a separate network to avoid conflicts with other tests running in parallel
3305+
// that use the default network/subnet
3306+
resource "google_compute_network" "test" {
3307+
name = "%s"
3308+
auto_create_subnetworks = false
3309+
}
3310+
3311+
resource "google_compute_subnetwork" "test" {
3312+
name = "%s"
3313+
ip_cidr_range = "10.2.0.0/16"
3314+
region = "us-central1"
3315+
network = google_compute_network.test.self_link
3316+
}
3317+
`, name, network, subnetwork)
3318+
}
3319+
32493320
// WARNING: This is not actually a check and is a terrible clean-up step because Composer Environments
32503321
// have a bug that hasn't been fixed. Composer will add firewalls to non-default networks for environments
32513322
// but will not remove them when the Environment is deleted.

0 commit comments

Comments
 (0)