diff --git a/mmv1/products/gkebackup/BackupPlan.yaml b/mmv1/products/gkebackup/BackupPlan.yaml index 26733710637e..78d744326cba 100644 --- a/mmv1/products/gkebackup/BackupPlan.yaml +++ b/mmv1/products/gkebackup/BackupPlan.yaml @@ -105,6 +105,40 @@ examples: deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: 'gkebackup_backupplan_rpo_daily_window' + primary_resource_id: 'rpo_daily_window' + vars: + name: 'rpo-daily-window' + cluster_name: 'rpo-daily-cluster' + deletion_protection: 'true' + network_name: 'default' + subnetwork_name: 'default' + test_vars_overrides: + deletion_protection: 'false' + network_name: 'acctest.BootstrapSharedTestNetwork(t, "gke-cluster")' + subnetwork_name: 'acctest.BootstrapSubnet(t, "gke-cluster", acctest.BootstrapSharedTestNetwork(t, "gke-cluster"))' + oics_vars_overrides: + deletion_protection: 'false' + test_env_vars: + project: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: 'gkebackup_backupplan_rpo_weekly_window' + primary_resource_id: 'rpo_weekly_window' + vars: + name: 'rpo-weekly-window' + cluster_name: 'rpo-weekly-cluster' + deletion_protection: 'true' + network_name: 'default' + subnetwork_name: 'default' + test_vars_overrides: + deletion_protection: 'false' + network_name: 'acctest.BootstrapSharedTestNetwork(t, "gke-cluster")' + subnetwork_name: 'acctest.BootstrapSubnet(t, "gke-cluster", acctest.BootstrapSharedTestNetwork(t, "gke-cluster"))' + oics_vars_overrides: + deletion_protection: 'false' + test_env_vars: + project: :PROJECT_NAME parameters: - !ruby/object:Api::Type::String name: 'location' @@ -164,7 +198,9 @@ properties: existing Backups under it. Backups created AFTER a successful update will automatically pick up the new value. NOTE: backupRetainDays must be >= backupDeleteLockDays. - If cronSchedule is defined, then this must be <= 360 * the creation interval.] + If cronSchedule is defined, then this must be <= 360 * the creation interval. + If rpo_config is defined, then this must be + <= 360 * targetRpoMinutes/(1440minutes/day) default_from_api: true - !ruby/object:Api::Type::Boolean name: locked @@ -189,12 +225,127 @@ properties: description: | A standard cron string that defines a repeating schedule for creating Backups via this BackupPlan. + This is mutually exclusive with the rpoConfig field since at most one + schedule can be defined for a BackupPlan. If this is defined, then backupRetainDays must also be defined. - !ruby/object:Api::Type::Boolean name: paused description: | This flag denotes whether automatic Backup creation is paused for this BackupPlan. default_from_api: true + - !ruby/object:Api::Type::NestedObject + name: rpoConfig + description: | + Defines the RPO schedule configuration for this BackupPlan. This is mutually + exclusive with the cronSchedule field since at most one schedule can be defined + for a BackupPLan. If this is defined, then backupRetainDays must also be defined. + properties: + - !ruby/object:Api::Type::Integer + name: targetRpoMinutes + required: true + description: | + Defines the target RPO for the BackupPlan in minutes, which means the target + maximum data loss in time that is acceptable for this BackupPlan. This must be + at least 60, i.e., 1 hour, and at most 86400, i.e., 60 days. + - !ruby/object:Api::Type::Array + name: exclusionWindows + description: | + User specified time windows during which backup can NOT happen for this BackupPlan. + Backups should start and finish outside of any given exclusion window. Note: backup + jobs will be scheduled to start and finish outside the duration of the window as + much as possible, but running jobs will not get canceled when it runs into the window. + All the time and date values in exclusionWindows entry in the API are in UTC. We + only allow <=1 recurrence (daily or weekly) exclusion window for a BackupPlan while no + restriction on number of single occurrence windows. + # Exclusion Window Object + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + name: startTime + required: true + description: | + Specifies the start time of the window using time of the day in UTC. + properties: + - !ruby/object:Api::Type::Integer + name: hours + description: | + Hours of day in 24 hour format. + - !ruby/object:Api::Type::Integer + name: minutes + description: | + Minutes of hour of day. + - !ruby/object:Api::Type::Integer + name: seconds + description: | + Seconds of minutes of the time. + - !ruby/object:Api::Type::Integer + name: nanos + description: | + Fractions of seconds in nanoseconds. + - !ruby/object:Api::Type::String + name: duration + required: true + description: | + Specifies duration of the window in seconds with up to nine fractional digits, + terminated by 's'. Example: "3.5s". Restrictions for duration based on the + recurrence type to allow some time for backup to happen: + - single_occurrence_date: no restriction + - daily window: duration < 24 hours + - weekly window: + - days of week includes all seven days of a week: duration < 24 hours + - all other weekly window: duration < 168 hours (i.e., 24 * 7 hours) + validation: !ruby/object:Provider::Terraform::Validation + function: 'verify.ValidateDuration()' + - !ruby/object:Api::Type::NestedObject + name: singleOccurrenceDate + # TODO (cmfeng): add exactly_one_of when it can be applied to lists (https://github.com/hashicorp/terraform-plugin-sdk/issues/470) + description: | + No recurrence. The exclusion window occurs only once and on this date in UTC. + Only one of singleOccurrenceDate, daily and daysOfWeek may be set. + properties: + - !ruby/object:Api::Type::Integer + name: year + description: | + Year of the date. + - !ruby/object:Api::Type::Integer + name: month + description: | + Month of a year. + - !ruby/object:Api::Type::Integer + name: day + description: | + Day of a month. + - !ruby/object:Api::Type::Boolean + name: daily + # TODO (cmfeng): add exactly_one_of when it can be applied to lists (https://github.com/hashicorp/terraform-plugin-sdk/issues/470) + description: | + The exclusion window occurs every day if set to "True". + Specifying this field to "False" is an error. + Only one of singleOccurrenceDate, daily and daysOfWeek may be set. + - !ruby/object:Api::Type::NestedObject + name: daysOfWeek + # TODO (cmfeng): add exactly_one_of when it can be applied to lists (https://github.com/hashicorp/terraform-plugin-sdk/issues/470) + description: | + The exclusion window occurs on these days of each week in UTC. + Only one of singleOccurrenceDate, daily and daysOfWeek may be set. + properties: + - !ruby/object:Api::Type::Array + name: daysOfWeek + description: | + A list of days of week. + item_type: !ruby/object:Api::Type::Enum + name: dayOfWeek + description: | + The day of the week. + values: + - :MONDAY + - :TUESDAY + - :WEDNESDAY + - :THURSDAY + - :FRIDAY + - :SATURDAY + - :SUNDAY + # Exclusion Window Object - End - !ruby/object:Api::Type::String name: etag output: true diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_rpo_daily_window.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_rpo_daily_window.tf.erb new file mode 100644 index 000000000000..9b6531ada4a4 --- /dev/null +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_rpo_daily_window.tf.erb @@ -0,0 +1,56 @@ +resource "google_container_cluster" "primary" { + name = "<%= ctx[:vars]['cluster_name'] %>" + location = "us-central1" + initial_node_count = 1 + workload_identity_config { + workload_pool = "<%= ctx[:test_env_vars]['project'] %>.svc.id.goog" + } + addons_config { + gke_backup_agent_config { + enabled = true + } + } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" + network = "<%= ctx[:vars]['network_name'] %>" + subnetwork = "<%= ctx[:vars]['subnetwork_name'] %>" +} + +resource "google_gke_backup_backup_plan" "daily_single" { + name = "<%= ctx[:vars]['name'] %>" + cluster = google_container_cluster.primary.id + location = "us-central1" + retention_policy { + backup_delete_lock_days = 30 + backup_retain_days = 180 + } + backup_schedule { + rpo_config { + target_rpo_minutes=1440 + exclusion_windows { + start_time { + hours = 12 + } + duration = "7200s" + daily = true + } + exclusion_windows { + start_time { + hours = 8 + minutes = 40 + seconds = 1 + } + duration = "3600s" + single_occurrence_date { + year = 2024 + month = 3 + day = 16 + } + } + } + } + backup_config { + include_volume_data = true + include_secrets = true + all_namespaces = true + } +} diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_rpo_weekly_window.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_rpo_weekly_window.tf.erb new file mode 100644 index 000000000000..d23f210917e4 --- /dev/null +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_rpo_weekly_window.tf.erb @@ -0,0 +1,69 @@ +resource "google_container_cluster" "primary" { + name = "<%= ctx[:vars]['cluster_name'] %>" + location = "us-central1" + initial_node_count = 1 + workload_identity_config { + workload_pool = "<%= ctx[:test_env_vars]['project'] %>.svc.id.goog" + } + addons_config { + gke_backup_agent_config { + enabled = true + } + } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" + network = "<%= ctx[:vars]['network_name'] %>" + subnetwork = "<%= ctx[:vars]['subnetwork_name'] %>" +} + +resource "google_gke_backup_backup_plan" "weekly_single" { + name = "<%= ctx[:vars]['name'] %>" + cluster = google_container_cluster.primary.id + location = "us-central1" + retention_policy { + backup_delete_lock_days = 30 + backup_retain_days = 180 + } + backup_schedule { + rpo_config { + target_rpo_minutes=1440 + exclusion_windows { + start_time { + hours = 1 + minutes = 23 + } + duration = "1800s" + days_of_week { + days_of_week = ["MONDAY", "THURSDAY"] + } + } + exclusion_windows { + start_time { + hours = 12 + } + duration = "3600s" + single_occurrence_date { + year = 2024 + month = 3 + day = 17 + } + } + exclusion_windows { + start_time { + hours = 8 + minutes = 40 + } + duration = "600s" + single_occurrence_date { + year = 2024 + month = 3 + day = 18 + } + } + } + } + backup_config { + include_volume_data = true + include_secrets = true + all_namespaces = true + } +}