diff --git a/changelogs/unreleased/1936-betta1 b/changelogs/unreleased/1936-betta1 new file mode 100644 index 0000000000..21c6349e10 --- /dev/null +++ b/changelogs/unreleased/1936-betta1 @@ -0,0 +1 @@ +Allow backup storage locations to specify backup sync period or toggle off sync diff --git a/pkg/apis/velero/v1/backup_storage_location.go b/pkg/apis/velero/v1/backup_storage_location.go index 7b477293a8..332e90b273 100644 --- a/pkg/apis/velero/v1/backup_storage_location.go +++ b/pkg/apis/velero/v1/backup_storage_location.go @@ -80,6 +80,11 @@ type BackupStorageLocationSpec struct { // AccessMode defines the permissions for the backup storage location. // +optional AccessMode BackupStorageLocationAccessMode `json:"accessMode,omitempty"` + + // BackupSyncPeriod defines how frequently to sync backup API objects from object storage. A value of 0 disables sync. + // +optional + // +nullable + BackupSyncPeriod *metav1.Duration `json:"backupSyncPeriod,omitempty"` } // BackupStorageLocationPhase is the lifecyle phase of a Velero BackupStorageLocation. diff --git a/pkg/apis/velero/v1/zz_generated.deepcopy.go b/pkg/apis/velero/v1/zz_generated.deepcopy.go index d61899f7e4..d79863e153 100644 --- a/pkg/apis/velero/v1/zz_generated.deepcopy.go +++ b/pkg/apis/velero/v1/zz_generated.deepcopy.go @@ -348,6 +348,11 @@ func (in *BackupStorageLocationSpec) DeepCopyInto(out *BackupStorageLocationSpec } } in.StorageType.DeepCopyInto(&out.StorageType) + if in.BackupSyncPeriod != nil { + in, out := &in.BackupSyncPeriod, &out.BackupSyncPeriod + *out = new(metav1.Duration) + **out = **in + } return } diff --git a/pkg/cmd/cli/backuplocation/create.go b/pkg/cmd/cli/backuplocation/create.go index c2981370f2..a4dfd5ad45 100644 --- a/pkg/cmd/cli/backuplocation/create.go +++ b/pkg/cmd/cli/backuplocation/create.go @@ -19,6 +19,7 @@ package backuplocation import ( "fmt" "strings" + "time" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -54,13 +55,14 @@ func NewCreateCommand(f client.Factory, use string) *cobra.Command { } type CreateOptions struct { - Name string - Provider string - Bucket string - Prefix string - Config flag.Map - Labels flag.Map - AccessMode *flag.Enum + Name string + Provider string + Bucket string + Prefix string + BackupSyncPeriod time.Duration + Config flag.Map + Labels flag.Map + AccessMode *flag.Enum } func NewCreateOptions() *CreateOptions { @@ -78,6 +80,7 @@ func (o *CreateOptions) BindFlags(flags *pflag.FlagSet) { flags.StringVar(&o.Provider, "provider", o.Provider, "name of the backup storage provider (e.g. aws, azure, gcp)") flags.StringVar(&o.Bucket, "bucket", o.Bucket, "name of the object storage bucket where backups should be stored") flags.StringVar(&o.Prefix, "prefix", o.Prefix, "prefix under which all Velero data should be stored within the bucket. Optional.") + flags.DurationVar(&o.BackupSyncPeriod, "backup-sync-period", o.BackupSyncPeriod, "how often to ensure all Velero backups in object storage exist as Backup API objects in the cluster. Optional. Set this to `0s` to disable sync") flags.Var(&o.Config, "config", "configuration key-value pairs") flags.Var(&o.Labels, "labels", "labels to apply to the backup storage location") flags.Var( @@ -100,6 +103,10 @@ func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Facto return errors.New("--bucket is required") } + if o.BackupSyncPeriod < 0 { + return errors.New("--backup-sync-period must be non-negative") + } + return nil } @@ -109,6 +116,12 @@ func (o *CreateOptions) Complete(args []string, f client.Factory) error { } func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { + var backupSyncPeriod *metav1.Duration + + if c.Flags().Changed("backup-sync-period") { + backupSyncPeriod = &metav1.Duration{Duration: o.BackupSyncPeriod} + } + backupStorageLocation := &velerov1api.BackupStorageLocation{ ObjectMeta: metav1.ObjectMeta{ Namespace: f.Namespace(), @@ -123,8 +136,9 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { Prefix: o.Prefix, }, }, - Config: o.Config.Data(), - AccessMode: velerov1api.BackupStorageLocationAccessMode(o.AccessMode.String()), + Config: o.Config.Data(), + AccessMode: velerov1api.BackupStorageLocationAccessMode(o.AccessMode.String()), + BackupSyncPeriod: backupSyncPeriod, }, } diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index 8ad6c7ef96..cf6a876623 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -194,7 +194,7 @@ func NewCommand(f client.Factory) *cobra.Command { command.Flags().Var(config.formatFlag, "log-format", fmt.Sprintf("the format for log output. Valid values are %s.", strings.Join(config.formatFlag.AllowedValues(), ", "))) command.Flags().StringVar(&config.pluginDir, "plugin-dir", config.pluginDir, "directory containing Velero plugins") command.Flags().StringVar(&config.metricsAddress, "metrics-address", config.metricsAddress, "the address to expose prometheus metrics") - command.Flags().DurationVar(&config.backupSyncPeriod, "backup-sync-period", config.backupSyncPeriod, "how often to ensure all Velero backups in object storage exist as Backup API objects in the cluster") + command.Flags().DurationVar(&config.backupSyncPeriod, "backup-sync-period", config.backupSyncPeriod, "how often to ensure all Velero backups in object storage exist as Backup API objects in the cluster. This is the default sync period if none is explicitly specified for a backup storage location.") command.Flags().DurationVar(&config.podVolumeOperationTimeout, "restic-timeout", config.podVolumeOperationTimeout, "how long backups/restores of pod volumes should be allowed to run before timing out") command.Flags().BoolVar(&config.restoreOnly, "restore-only", config.restoreOnly, "run in a mode where only restores are allowed; backups, schedules, and garbage-collection are all disabled. DEPRECATED: this flag will be removed in v2.0. Use read-only backup storage locations instead.") command.Flags().StringSliceVar(&config.disabledControllers, "disable-controllers", config.disabledControllers, fmt.Sprintf("list of controllers to disable on startup. Valid values are %s", strings.Join(disableControllerList, ","))) diff --git a/pkg/controller/backup_sync_controller.go b/pkg/controller/backup_sync_controller.go index 4845290b28..d86e7dd795 100644 --- a/pkg/controller/backup_sync_controller.go +++ b/pkg/controller/backup_sync_controller.go @@ -48,6 +48,7 @@ type backupSyncController struct { podVolumeBackupLister listers.PodVolumeBackupLister namespace string defaultBackupLocation string + defaultBackupSyncPeriod time.Duration newPluginManager func(logrus.FieldLogger) clientmgmt.Manager newBackupStore func(*velerov1api.BackupStorageLocation, persistence.ObjectStoreGetter, logrus.FieldLogger) (persistence.BackupStore, error) } @@ -77,6 +78,7 @@ func NewBackupSyncController( podVolumeBackupClient: podVolumeBackupClient, namespace: namespace, defaultBackupLocation: defaultBackupLocation, + defaultBackupSyncPeriod: syncPeriod, backupLister: backupInformer.Lister(), backupStorageLocationLister: backupStorageLocationInformer.Lister(), podVolumeBackupLister: podVolumeBackupInformer.Lister(), @@ -88,7 +90,7 @@ func NewBackupSyncController( } c.resyncFunc = c.run - c.resyncPeriod = syncPeriod + c.resyncPeriod = 30 * time.Second c.cacheSyncWaiters = []cache.InformerSynced{ backupInformer.Informer().HasSynced, backupStorageLocationInformer.Informer().HasSynced, @@ -134,6 +136,30 @@ func (c *backupSyncController) run() { for _, location := range locations { log := c.logger.WithField("backupLocation", location.Name) + + syncPeriod := c.defaultBackupSyncPeriod + if location.Spec.BackupSyncPeriod != nil { + syncPeriod = location.Spec.BackupSyncPeriod.Duration + if syncPeriod == 0 { + log.Debug("Backup sync period for this location is set to 0, skipping sync") + continue + } + + if syncPeriod < 0 { + log.Debug("Backup sync period must be non-negative") + syncPeriod = c.defaultBackupSyncPeriod + } + } + + lastSync := location.Status.LastSyncedTime + if lastSync != nil { + log.Debug("Checking if backups need to be synced at this time for this location") + nextSync := lastSync.Add(syncPeriod) + if time.Now().UTC().Before(nextSync) { + continue + } + } + log.Debug("Checking backup location for backups to sync into cluster") backupStore, err := c.newBackupStore(location, pluginManager, log) diff --git a/pkg/generated/crds/crds.go b/pkg/generated/crds/crds.go index a52880f58d..85f746f3c0 100644 --- a/pkg/generated/crds/crds.go +++ b/pkg/generated/crds/crds.go @@ -30,7 +30,7 @@ import ( var rawCRDs = [][]byte{ []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec\x1c\xcbn#\xb9\xf1\xee\xaf(8\x87\xd9\x05,\r\x06\xb9\x04\xbe\xcdz\x1c\xc4\xd8ɬ\xb16\x9cC\x90\x03\xd5]\x92\x18\xb3\xc9\x0eɖ\xad\x04\xf9\xf7\x80E\xb2\xdf\x0fjV\xd9\xc1b͓M\x91\xc5z\xb3X,\xf6\xc5j\xb5\xba`%\u007fBm\xb8\x92\xd7\xc0J\x8e\xaf\x16\xa5\xfbϬ\x9f\xffd\xd6\\\xbd?|ؠe\x1f.\x9e\xb9̯\xe1\xa62V\x15?\xa3Q\x95\xce\xf0\x13n\xb9\xe4\x96+yQ\xa0e9\xb3\xec\xfa\x02\x80I\xa9,s\xdd\xc6\xfd\v\x90)i\xb5\x12\x02\xf5j\x87r\xfd\\mpSq\x91\xa3\xa6\x15\xe2\xfa\xdfU\xf2Y\xaa\x17\xf9\xfd\x05@\xa6\x91 <\xf2\x02\x8deEy\r\xb2\x12\xe2\x02@\xb2\x02\xafaò\xe7\xaa4\xeb\x03\n\xd4j\xcdՅ)1s\xcb\xed\xb4\xaa\xcakh~\xf0S\x02*\x9e\x8c\x1fh6u\bn쏭\xce\xcf\xdcX\xfa\xa1\x14\x95f\xa2^\x89\xfa\f\x97\xbbJ0\x1d{/\x00L\xa6J\xbc\x86\xcb\xcb\v\x80\x03\x13<'\xb4\xfdb\xaaD\xf9\xf1\xfe\xee\xe9\x8f\x0f\xd9\x1e\v\xe6;\x01r4\x99\xe6%\x8d\v\xab\x027\xc0\xe0\x89p\x06\x1d\xd8\vvϬ\xfb\xaf\xd4hPZ\x03v\x8f\x90\xb1\xd2V\x1aAm\xe1\xc7j\x83Z\xa2E\x13 \x03d\xa22\x165\x18\xcb,\x02\xb3\xc0\xa0T\\Z\xe0\x12,/\x10\xbe\xfbx\u007f\aj\xf3O̬\x01&s`ƨ\x8c3\x8b9\x1c\x94\xa8\n\xf4s\xbf_\a\x98\xa5V%j\xcb#\a]kiM\xddף\xeb\x9d#\u070f\x81\xdc\xe9\tz\xf4\x83\xb41\aCLqt\xd8=7\xa01\x90I\fl\x81\x057\x84ɀ\xf4\x1a\x1eP; `\xf6\xaa\x12\xb9S\xae\x03jǧL\xed$\xffw\rـU\xb4\xa4`\x16\x83Pc\xe3Ң\x96L8\x91UxE\x8c(\xd8\x114\xba5\xa0\x92-h4Ĭ\xe1\xafJ#p\xb9Uװ\xb7\xb64\xd7\xef\xdf︍v\x92\xa9\xa2\xa8$\xb7\xc7\xf7\xa4\xed|SY\xa5\xcd\xfb\x1c\x0f(\u07b3\x92\xaf\bOIV\xb1.\xf2?D!\x9bw-\xc4\xec\xd1钱\x9a\xcb]\xddM*;\xc9f\xa7\xbb^{\xfc4\x8fn\xc3M\xd7\xe5\x98\xf0\xf3\xed\xc3c[\xb3\xb8鲘\x98\xdbL3\r\x9f\x1d_\xb8ܢ\xf6r\xdajU\x10D\x94\xb9W-\xd2J\xc1Qvyl\xaaM\xc1\xad\x13\xec\xbf*4N{\xd5\x1an\xc89\xc0\x06\xa1*s\xa7tk\xb8\x93p\xc3\n\x147\xcc\u0e79\xec\x18jV\x8e\x83\xcb|n\xbb\xb0\xee@Ϝ\xba;z\x9aQ\x81x{~(1먽\x9b÷<#冭ҍ\xb9{W\xb2n\x01\x1c39\xd7\xf05\x13U\x8e\xf9\x17\xe7\xcfJ\x96\xf5\u007f\xef\xa1r;\x18N\x9e\x98q\xe9\xd4\xc59>gY\xb2\xf9\x95\xfc\r\xd3\xd8\x03\n\xe0Dƥ\x87F\x9ed\x8f#h\x93aY,\x06XM0<\xc0\xae\x84`\x1b\x81\xd7`u\xd5_\xda\xcfcZ\xb3\xe3('\xe2N\x94ƈzt0\x18\xc13\xf2\xa3\xb5Y\x10/~Cl\xd8+\xf5L\x92\xbba\x06sP^\ru%Є\x85r\xf2/\x8d]_M\x00\xae\xa5\xe0\xf7?\xc16(\xc0\xa0\xc0\xcc*=Ɔy\xa1\xfa\xb6\xec\xa3&x7⭂\xd3\f.\xb4\xed\xa8\xd4$L\x80\x97=\xcf\xf6~\xafr\xfaBP Wh\xc8~YY\x8a\xe38q0/i\xdffL\xb8i\xb3\xc6܇54\xeb\xa6-\xfa\xb9\xa6-x\xbc./k\xd1\xff~X\x19\x1d\xf7Ɋy7\x98xN\xc5tL\xe4.\xbc\xbc\xdb\x02\x16\xa5=^\x01\xb7\xb1\xd7E\xb0\x8cN=\x93\xec\xa9\xd7\xfe\xcd\t\xe2T\x9d\xbe\xeb\xcf;\xa3N\xffB)\xd4K\xfff\x84@\xce\xfe!\xf8\xfaD\x01|nϹ\x02\xbe\xad\x05\x90_\xc1\x96\v\x8b\xba'\x899rռ$~)\v\x96w*\xd7\nf\xb3\xfd\xed\xab\x8b\x8eL\x93\xafH\xe2F\u007f\xaa\x8f)cT\xdd\xddLg\xa1\x02\x9d\x90\xb8\xc6\u009f\xbb\x1e\x89\x83M\x0fE>\x1f\xbf|\xc2|\x9a)\x90\xa2a\x03\x12>\xf6\xd0l/\x1bB\xe44\x02B\x90R\x9f.\xfc\x91\xf9\n\x18<\xe3\xd1G\x17\xee\x00_\xa2fn\x197x\x11\xa2F:\xb7\x93B=㑀\x84\xa3\xf8\xc2\xdc4\xd1\xfb\xf6\x8c\xc7\xe5A=\xb69l\xb8\t\xa9\x05\xc7?\xd7A\f\xa0\x93^*ˀ\x12)\xd1\xc3,\x11\x05\xa9.\"\xb6\xc8\xed\x93ɫ\xc5\xd4$\x03\xbc \xdf\x19/\x14\xa7\xed{^&\x11\xe8\\'\x18$\x9b\x88\x89\x94'&x^/\xe3\xf5\xfbN^\xc1\x17e\xef\xe4T\xb0\xdam\xb7\xaf܄\xfc\xd5'\x85拲\xd4sv&z\x94Of\xa1\x9fF&$\xbd\x1bv\xf4\xb7\x134\x8bJ\xec\u06dd?a\xd5\"\xe1\x06\xee\xa4;Cx^\xf9\x8c\x9a_l\xce\xdbw[Q\x19\xca\xc0H%W\xb4٭\xc7\xd6\t,NT\xe4\xb6\x14\x86h\xd5K\xfa\xe5\x92 >\xba}\xc1\xcf\xf6\xd9A\xc12\xcc!\xaf\x88\x89\x94\xeeb\x16w<\x83\x02\xf5nz#h\xb7\xd2\xf9\xec\x94\xe5\x93|\xa9o'\xe9S\xca\xd6\x1c[p\xc6\xf9\x12\x1a+g\x9b\x8bc\xa2h\x17\x06\x8e&\xbc\xa6\a.\xd1A\x9b$\xc5\r\v\xdcdyN\x17\tL\xdc'{\xefd\xce\x0f\xf7m\x8f\x92\xdf\xe3\nV:\xeb\xfc\x8f۪Hi\xff\v%\xe3z\xd1B?\xd2u\x80\xc0\xce̐\x15j/\xe2\xe0s\x03N\x9a\a&\xfaY\xd2\x11\xb2\x94\xf3\x1a(\xfc6\xac\xb6\x83H\xe3\n^\xf6\xca\xf8]q\xcbQ\xe4\xc0\xe7\"-\xd7.\x9f\xf1xy5\xb0\xf1\xcb;y\xe9\xb7\xe7\x81\xc5ƽ|\x01\xb0\x92\xe2\b\x974\xf3\xf2\xebC\x97$\xadK\x18DwCi\xc1\xac;\xcd\xc5]\xdcM\xab\xef!\\(:\x8dm\x82Ε\xca\xd8D$\ue571>C\xd7\t\x1eGrC\xf3g\x9a\x90\x13\x02\xb6\xf5w?JǴ\xbfsd\xbdT\xa5\x93\x92\xc1\xd1\x04\xe7\x00b\x1e@2!ಱQ\xef\x1f/\xfd]\x00-\xc12\n\vf :U(\xb5\xcaИ9uX\xf4\xbc\v\t\xb7:\xd9\xc6\xfc\xa1§\xda\xe7\x92{\xb1\xa5\x86\x8d\x8e5'\x85ٷ\xaf\xad\x1c\xa03m\xf7\xff\xbc\x9a\x9d\x86\x11\xd0\x1dkQ0\xb9\xb8Y\f\x90\xbb\xf1\xf3\xa2)\x040>d\u05fb\x8a\xcc85\xd2\vJ\xf3m7\u0602\xcb;\x02\x0e\x1fκ\x1dCt\x89xzH}\x13g6l\xae;\xbcm\x96j\x98r\x1fk/{\xd4ؑ\xd403L\xe1\x9cT\xb6u\xd6A\xb0\xf8\x8a\xad;u,v\fY6\x1f\x1f\xb6N_\x0eá\xbc'-\xcfZ1K\xc4\xe3\xe3g\x8f\xb8\xe5\x05\xae?U\xfe \xb7*\x996\xe8\xf8\x17\t\xf2\x936\xeeϽz\x19 ,T\xa0\xf4\x87>\xbe\x1a)\x87G\xa7\xc5d\xac\xfd{٨`\x91M\xf3\xea\xf84>\xa7\x15\x8b\xb6\x84\xe2\x0f6j;5k@`\xeb1\xaf\x8b\xf6}E˹\x9e\xa8\x8d;\xe7\xf1'\x92\x96\xd9\xca,=\x92\xa4A\xf1As\xc8\xf8V\x9a^\x98y\x00^\x19O~'\x19\xd2[\x9d\xe7\xe3s2\xb9\x19\x8e\xa7\xe7\xc4:\xf7HQZ\x8dE%\u007fa\xa6N\xa0\x8dx\xb4\x06\x98\x9fG\xc1\x80\x83\x859\xe0\x01%(I\xf92z\xc1\xe5\x1f\xb1\xf7\xe7\fϯ-\x18!\x1dW\x95B\xb1\x91~$\u007f\xa4\x0f\xa8ߙI\x88\x95\tɑ\x11\xf2\xfb\x9a\xb5U\xba`\xf6\x1arfq5\x020\xc1\x8f\x8d\xa8\x14%\x8f\x17\x9en\xd2\x10o\x1d\x94w&\x95\x10\"$\x9e\v4\x86\xed\xe2\x9b\xcd\x17\xe7\x8ev(\xdd&7\x92%\n\xa1X\x93\xb8\xec\xbe_\xf4':\x96Yw\xfe\xf5\xa8\x85#lkԻ\xa1\xcd\t\xb5s'l\x1a\x18\x9eQ\a\xff<\xeeH\xb8\xb4\xb8\xc3nx\x84\xaf%\xd7˾\xfc\xb6\x1e\xe68BGw\xb2\xf0\xe6#\x02(\xf8\x8e;\x87\xe8\x04\xbbcz\xc3v\xb8ʔp\xe7(\xaed\x1f\xa3\xff\x8f\\\xe9y\xe8,!\xf7nD}\xcbӲy\x8cB\x19\xdf/\xc7n\x03V\xf0\x05\xfb\xae\xde'\xf81\u007f\xaa\xbf\xc80\x18p'\xef\xb5ڹ\xc8i\xf0\xd3M\xb4\xee\xc1/\xf7L[΄8z\xf0\x13\xab\x0e\xba?\xa1\xb3\xaf\t\x87:\xc2@c\x99\xb6i\xbe\xeb\xa13t\xc1m\x11\\\xcc\xd7\xf0\x80%sF2Pf\xba\xaa\xbe\xe9\u007f|\xe3ʅ\xb6\xf1\x83\x14\xfe\x03\x03ٞ\xc9\x1d\xbdi\x05\x8d\xb4\xdb\xfb\xa7+\x03\x88\x1d?\xd4\xf1;]\xd4\u007f\x1d\x97\xd3|\xa2\xe3v\xd9\xf9<\xf5\x06\xf7\xf2\x8f\xce\r5\xf0\xa2\xcb\xf8\x8eo\x87\xdbrY\n\x9e9l\xbf\xffFy\xc5\xc3\xf0s\x1dCr\xc3\xe7:\x82Y\x06\xbd\xf1r\x88\x00\xd2]Z782\x1f\xadu\a\xe5\xe1\x81r&:j&E\x9c\xac\xb2L\x80\xac\x8a\rj\x12A\x1c0``\xfc\x96I\x04\x15\xee\xc0&ádBj\xe7p\n!\xf5\xa4)BL\x95eh̶\x12bx\U000ad8cd3R\xf5´\v1\xe7\r\xe0oa\xd0\xc8\xfe\x1b\xe6\x9fw\anm\xc0\x11\xbf_i\v\x1e\x89b{]\xf5g\x8a\x0e\x1f\x9a\xff\x88}\xab\xf0M\xa2\x83\xaf\xa4 \x87\x97\xb7\xac3\xa0\x12z\x9aИe\x19:\xdd\xfd\xd2\xff<\x11}L\xa8\xf9\x02\x11\xfd\x9b)\xe9\xf3\x1b\xe6\x1a\xfe\xfe\x8f\v\b'\xac\xa7\x88\x87\xeb\xfc_\x00\x00\x00\xff\xffµ\n\x80\xd2I\x00\x00"), - []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcWAs\xdb6\x13\xbd\xebW\xec\xf8;\xf8\xebLE5\xed\xa5\xa3[\xe2\xf4\x90\xa9\xd3x\xac\xd4=\xb4\x9d\tD\xac$\xd4\xe0\x82\xc5\x02r\xdc_\xdfY\x00\xa4D\x8a\xb2\x9d\x99\xb6\xbc\x01X.\x1e\u07be],f\xf3\xf9|\xa6Zs\x87\x9e\x8d\xa3%\xa8\xd6\xe0\xe7\x80$#\xae\xee\xbf\xe7ʸ\xc5\xfe\xd5\x1a\x83z5\xbb7\xa4\x97p\x159\xb8\xe6\x16\xd9E_\xe3[\xdc\x182\xc18\x9a5\x18\x94VA-g\x00\x8a\xc8\x05%\xd3,C\x80\xdaQ\xf0\xceZ\xf4\xf3-Ru\x1f\u05f8\x8e\xc6j\xf4i\x87n\xff\xffG\xba'\xf7@_\xcd\x00j\x8f\xc9\xc3G\xd3 \aմK\xa0h\xed\f\x80T\x83KX\xab\xfa>\xb6\x1c\x9cW[\xb4\xae\xce\xdbU{\xb4\xe8]e܌[\xace\xf7\xadw\xb1]\xc2a!{(\xc8\xf2\xa9\xde$g\xab\xec\xec\xba8K\xeb\xd6p\xf8\xf1\xbc͵\xe1\x90\xecZ\x1b\xbd\xb2\xe7`%\x136\xb4\x8dV\xf93F3\x00\xae]\x8bK\xb8\xb8\x98\x01\xec\x955:-d\xa0\xaeEz}\xf3\xee\xee\xbbU\xbd\xc3F\xe5I\x00\x8d\\{\xd3&\xbbi\x88`\x18\x14t\xbb\xc0\xc3\x0e=\xc2]b\x03\x04\x02r\xc1S<\x02\xb8\xf5\x1fX\a\xae\xcaD\xeb]\x8b>\x98\x8e2\xf9\x8eT\xd3ύ\xc0\\\n\xdal\x03Zt\x82\fa\x87P\xa2\x8d\x1a8\x9d\x04\xdc\x06\xc2\xce0xl=2R8\xb0\xdf#ڀ\xa2\x82\xab\x82\x15zq\x02\xbcs\xd1j\x11\xd7\x1e}\x00\x8f\xb5ے\xf9\xab\xf7\xcc\x10\\\xdaҪ\x80%N\xddg(\xa0'e\x85\xe7\x88_\x83\"\r\x8dz\x04\x8f\xb2\aD:\xf2\x96L\xb8\x82\xf7\xce#\x18ڸ%\xecBhy\xb9XlM\xe8\xf2\xa4vM\x13Ʉ\xc7ER\xbbY\xc7\xe0Y\xf9\x99ԙ\xb53g\x99\xa8ţ\xa9\xfe\xb1\xbe\u007fu\x18\xa5\x9a8//\xf3\xb4\x00\xc0\xf2z\xd0GD\x96\xac*3\x87\x02/\x15\xb4\r\xa8\u007f\x1a\xbf\xca/.\x06O\xeb4\xac\x1d\xe5Ύ\x97\xf0\xeb\xef\xb3\xec\x15\xf5]\x87C&\xff\x0e\x00\x00\xff\xffw\x9a\xf7\xf6\xd8\x10\x00\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcXAs\xdb6\x13\xbd\xebW\xec\xf8;\xf8\xebLE'\xed\xa5\xa3\x9b\xe3\xf4\x90\xa9\xd3x\xac\xd4=\xb4\x9d\tD,%\xd4\xe0\x82\xc5\x02r\xd4_\xdfY\x10\xa4D\x8a\x92\x9d\x99\xb4\xbc\x01X.\x1e\u07be],9\x9b\xcf\xe73\u0558\a\xf4l\x1c-@5\x06?\a$\x19q\xf1\xf8\x03\x17\xc6]m_\xaf0\xa8׳GCz\x017\x91\x83\xab\xef\x91]\xf4%\xbe\xc5ʐ\t\xc6ѬƠ\xb4\nj1\x03PD.(\x99f\x19\x02\x94\x8e\x82w֢\x9f\xaf\x91\x8aǸ\xc2U4V\xa3O;t\xfb\xff?\xd2#\xb9'\xfaf\x06PzL\x1e>\x9a\x1a9\xa8\xbaY\x00Ekg\x00\xa4j\\\xc0J\x95\x8f\xb1\xe1\xe0\xbcZ\xa3ue\xbb]\xb1E\x8b\xde\x15\xc6\u0378\xc1Rv_{\x17\x9b\x05\xec\x17Z\x0f\x19Y{\xaa7\xc9ٲuv\x9b\x9d\xa5uk8\xfct\xda\xe6\xd6pHv\x8d\x8d^\xd9S\xb0\x92\t\x1bZG\xab\xfc\t\xa3\x19\x00\x97\xae\xc1\x05\\\\\xcc\x00\xb6\xca\x1a\x9d\x16Z\xa0\xaeA\xba\xbe{\xf7\xf0\xfd\xb2\xdc`\xad\xdaI\x00\x8d\\z\xd3$\xbbi\x88`\x18\x14t\xbb\xc0\xd3\x06=\xc2Cb\x03\x04\x02rƓ=\x02\xb8՟X\x06.\xf2D\xe3]\x83>\x98\x8e2y\x0eT\xd3ύ\xc0\\\n\xda\xd6\x06\xb4\xe8\x04\x19\xc2\x06!G\x1b5p:\t\xb8\n\xc2\xc60xl<2Rس\xdf#\xaa@Q\xc6U\xc0\x12\xbd8\x01\u07b8h\xb5\x88k\x8b>\x80\xc7ҭ\xc9\xfc\xdd{f\b.miU\xc0\x1c\xa7\xee1\x14Г\xb2\xc2s\xc4oA\x91\x86Z\xed\xc0\xa3\xec\x01\x91\x0e\xbc%\x13.\xe0\xbd\xf3\b\x86*\xb7\x80M\b\r/\xae\xae\xd6&tyR\xba\xba\x8ed\xc2\xee*\xa9ݬbp\x9e\xaf4n\xd1^\xa9\xc6\xcc\x13NjeZ\xeb\xff\xf9\x9cC|y\x00,\xecD\x00\x1c\xbc\xa1u?\x9d4z\x92fQg\x1b\xe3\xf6\xb5\x16\xee\x9eM\x99\x12\x12\xee\u007f\\~\x84n\xd3\xc4\xf8\x90\xe2D\xee\xfe5\xde\xf3,\xbc\x18\xaaзq\xaa\xbc\xab\x93G$\xdd8C!\rJk\x90\x86\x1cs\\\xd5&H`\xff\x8a\xc8A\xc2Q\xc0M*\x0e\xb0B\x88\x8dV\x01u\x01\xef\bnT\x8d\xf6F1~m\x96\x85P\x9e\v\x83\xcf\xf3|X\u0086\x86-9\xfdtWZ&\x032\x99\x84\xcb\x06\xcbA\x16\x88\vS\x99\x9c\x94\x95\xf3\xa0rR\x0e(\x9ctV\x1c\x98L%gJвD\xe6\xf7N\xe3p~\x04\xf6\xba7\x1b\xa0k\xd0׆\xd35\x90\xb0\xc9\\[$ W\xad\x91S\xe8\vL1ZA\x8a\xf5\x18\xc2\x1c\xeeQ\xe9\x0fdw\x93\v\xbfz\x13\xc6\x1bL\x06L\x9e\x16\xd6rG\xe5\x1dz\xe3\xf4\xd9\xe3\xbe\x19\x19\xf7\x87\u07b8'\xa8\x92N)\u061d\xd4\r\xdeQ9.\x8c\xdds}\xf7\xae+\x92m6\xe4\xe4\xc9\xdc\x14p\x9d\x93\xd0U\xf0\n\xb4a\xb5\xb2\xc8\xc9\xe5\x98\x1e\xb9\xd3du\x01\xc1\xc7\x17\x1f\xbatT\x99\xf5\xf8\xa8J\xebt\x17+{wB\x15g\x9d\x8e\xb8\xbaI{He\x11\x054\xdem\x8dF?\uf11b1D\x9f\x15l\xd0j\x1e\x9fn2{\xa0\xaf6Y\xd7gC\xf6\xe1в\xbf\xd32\x8a.\x990H\x99c \x149+?\xd6\x15HDKG$Q\n\x0eT\u007f\x9eK\x1e\ao\xf4\xea\xa9\x04\x93g\x15\xcbG\f\xc7\xf3c\xd5%3a2\xe5Q;\n\x0e\"c\xe2\xf6<\x80gb&\b\xb12\x9f\x9fEq\x97\xcc:\x14\x8d\n\x1b0\xc4F#\xa8\tL\x13\xb5\xa8{z\x95\u007fhZ\xb5}!bI3\xe3\xf1(S\xe7\x19\xc6K5ԅ\xf0\xac|\xee\xb2Q\u007f\xeen\x9c\xba\x8eqU\x9b\xd6\xef\xd1)\xa6N0\x1fjz\xb0\xd2m\xfa\xec\xbd\x12T\x88\xfc\x857Kz'\x1b\xaerB\x94\xd1{\xa4\x90\x1d\x82\xab\x86wC\xd7\xfe\xfd۷\xcb\xc5\xc1\xf5\"\x1d\nA\xa4Ȩ\xdbjQ\xc0\xef\x04o\xa5\xdf(\xa5\x0fX\br\xb9\xfa\xf9HN\xe4\x9e\xe4\xe5\x03o\xc9\x018J\xa7M\x97\xab4pm{\x92\x96\x9e\x8c\xb5\xd2dx\xac\xdd\x16\xf5\x91Ki\x11<\xda\x1d(\xa1\a\xb6\xdf\x15\xaf\x8a\x8b\xff\xf8겊\x83\xdcE\xa8\xefqk\xc6\xcd\xf41\x9b\xb7G\xf6\x9d\xaa\xfb\xdbF\x06\x9f\xba>\xe6\xcag\xb3OGǯ\x8c\x95&k\"\x05\xf6_\nm\xe7\xcc\x01\x82\xa91\x8d\xde,o/9}\xccI\x83x\xe4\xf4I\xc2\xc7\t\xa0\xf4\xd7.\xf7\x85\x91\x03\xfa\x89`\xf7\xb12\f\xe4\xc0:Z\x0fR\xa4}r\x97\b\xceC+\x1d\xe7Ac\xc025\xb6\xe5F\xd1\x1a\xf7\x8d~\xc6~\x80R\x84q\x8ct\xa8\x8e\xbd\x1a\fMK\xe1\x051\x94\x0fճ\xf1\xbb\x1d\x98v\xa1\x1b2ܣα\xb4\x87ߢ/\xe6zd]9_\xab\xb0\x00!r.[}\x95\x1e\xa4\xd9(>\u007f\xe0;\xb1\xe8\xceyX\x92z\xa9>[\x80\xe0d\x1a^o\x95I\xa8\x8fV~!ub\xed\xc4Y&j\xf1h\xaa\xffC\xb1}\xbd\x1f\xa5\x9a8Ͽ#\xd2\x02\x00\xcb'\x93> 2gU\x9e\xd9\x17x\xa9\xa0M@\xfd\xf3\xf8W\xc4\xc5\xc5\xe0\u007fB\x1a\x96\x8e\xdaΎ\x17\xf0\xdb\x1f\xb3\xd6+\xea\x87\x0e\x87L\xfe\x13\x00\x00\xff\xff\xe7g\xca\xe7\xcd\x11\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xac\x96\xcdn\xe46\f\xc7\xef~\nb{\xd8\x16\xe8x\x10\xf4R\xf8\xd6f\xf7\x10\xb4\r\x82d\x91KуF\xe2\x8c\xd5ؔJR\x93\xa6O_H\xb2\xe7+\x0e\xb2\x05\xea\x9b(\x8a\xa4~\xfcKV\xb3Z\xad\x1a\x13\xfd#\xb2\xf8@\x1d\x98\xe8\xf1oE\xca#i\x9f~\x94և\xf5\xfej\x83j\xae\x9a'O\xae\x83\xeb$\x1a\xc6{\x94\x90\xd8\xe2'\xdcz\xf2\xea\x035#\xaaqFM\xd7\x00\x18\xa2\xa0&\x9b%\x0f\x01l \xe50\fȫ\x1dR\xfb\x946\xb8I~p\xc8%Ü\xff\xdbDO\x14\x9e\xe9\xbb\x06\xc02\x96\b_\xfc\x88\xa2f\x8c\x1dP\x1a\x86\x06\x80̈\x1d8\x1cPqc\xecS\x8a\x8c\u007f%\x14\x95v\x8f\x03rh}h$\xa2\u0379w\x1cR\xec\xe08Q\xd7Ou\xd5=}*\xa1~.\xa1\xeek\xa82;x\xd1_\xde\xf2\xf8\xd5O^qHl\x86傊\x83xڥ\xc1\xf0\xa2K\x03 6D\xec\xe0Ç\x06`o\x06\xefʾk\x81!\"\xfdtw\xf3\xf8Ã\xedq4\xd5\b\xe0P,\xfbX\xfc\x96\x8a\x03/``J\x01\x1a\xa6\xcc\x10\b!0\x8c\x81\x11j\x19\xd2N!#\x87\x88\xac~F\x93\xbf\x13m\x1cl\x17\xc9?\xe6\xea\xaa\x0f\xb8\xac\x06\x14\xd0\x1ea\xea):\x90R9\x84-h\xef\x05\x18#\xa3 U}\x9c\x84\x85\xecb\b\xc2\xe6O\xb4\xda\xc2\x03r\x0e\x02҇4\xb8,\xa1=\xb2\x02\xa3\r;\xf2\xff\x1c\"K\xde_N9\x18\x9d;7\u007f\x9e\x14\x99̐\xb9&\xfc\x1e\f9\x18\xcd\v0\xe6\x1c\x90\xe8$Zq\x91\x16~\xcbpE\x8d\x1fpk\x9ca\xe3]5 \xabV\xb1ZU\x00\xca9\xcfJ\xc2$\xbf\x00\xda;\x8e\xdeZ\x8cu\x87\xaeyL\x1b\xdc$c[\x8cy\x85i\xfd7\xc9=:\xbfwo+\x00\x1d1W\xb87\x03\x12\xab!\xac\xc0%k+\x00\xa7\x06\\A\xeb\xf7\xcez\xd5F\xfc;!15;\xb4\x18}c|E\x01\xb5\xac\xdbE\x9f\xc2\n\x8e\x03e\ue229\xec\xe7\xc3Xf]\xca\xe4\x11k\x88\u007f]\x1a\xfdlƌ`ST\xf6\x12D\x1e$\xe3\xbadU\xbc\x18\xae\x00H\xfb\x80+x\xf5\xaa\x02\xd8)kڼ\xc7\x02\xc8\at?\u007f\xfd\xf4\xf0\xe3\x9d\xeeqP%\b\xd0\"\xe9hBΛ\x03\x02C\xa0`,\x0f\xec\x0f+\x82r\xa0\"\x9b\xad\xd2\f\xdb\xe8\a\xd8(\xfd\x98\xc2X\x13\xc0o\xfeB\xcd@\xec\xa3\xea\xf0\x1dP\xd2=(\xa9V\x12\xc1\xfa\x0e\xb6\xc6b3N\t\xd1\a\x8cl&\xfa\xe4;\xd1\xce!6\x03\xfcZvTr\xa0\x15\xb5 \x01\xf7\b\xe3\x99c\v\x94w\v~\v\xdc\x1b\x82\x88!\"\xa1+\xfa9)\v\x92\xa2܈\xbc\x81;\x8cR\x04\xa8\xf7ɶ\"\xb1\x1dF\x86\x88\xdaw\xce\xfcs\xa8L\u008b,i\x15O'<}\xc61F\xa7\xac\x9cE\xc2w\xa0\\\v\x83z\x82\x88\x99\x9d\xe4N\xaa\xe5\x14j\xe07\x1f\x11\x8c\xdb\xfa\x15\xf4́V77\x9d\xe1\xc9-\xda\x0fCr\x86\x9fn\xb2\xe6\xcd&\xb1\x8ft\xd3\xe2\x0e\xed\x8d\n\xa6\xce8]\xf6F3\xb4?\xc4\xd1I\xf4\xfa\x04\x18?\x89H\x88\xa3q\xdd!\x9c\xf5z\x95f\xd1kQC\x99V\xe0\x1eٔ\x90\x90\xb0\xfexw\x0fӢ\x99\xf1s\x8a\x8b,\x0e\xd3\xe8ȳ\xf0b\xdc\x16c9\xa7,*\xa9\x88\xae\r\xde8\xce?\xda\x1at\xe7\x1cS\xda\f\x86iR\xa9\x1cG\x03\xb7\xb9E\xc0\x06!\x85V1\xb6\r|rp\xab\x06\xb4\xb7\x8a\xf0\xfffY\b\xa5Z\x18|\x99\xe7\xd3Fv\x9eX\xc89\x84\xa76\xb3x 3\xa3\xde\x05\xd4r<\u0091\xcc3[\xa3\xb3\xc0a\xeb#\xa8\xa3oG\x96\x9a\x93\xbaK\xceˠT\xec\x90\xcfc3\x14\xf79E\x16\xde\xf7\xea\xbcA\xbc\xc1\xa6k\xc4\xe54B(\xbe\u007f\xdb\xcc\xea][}I\x92\x8b\x18&e\xcaօG\xb1\xb14\x96S4\xf3E\xe5C\x97\x86\xa5\xe25\xfc\x92\x91~\xf6\xdd3\xa3\xb7ޱ\xe8\xf7\x99\x94\aoӀwN\x05\xea=?\x938\xddv\x87\xf6?O[\xa3\xf4Q\xbc\x86h\x1c^#%\xbb\x88hQ\x87ӗ\xaf\xbb\x97H\xfe\xa2\x06\x9cH\x96\t\xa5\x9d\"\xc8M\x1b\x1d2\xd2\xd1\xf4{\xc3=\xec{\xa3\xfb\x85\xaa\x90\xa7\xe5\xf3\x91nB\xe4\xb5\xc9\xfe\xfco\xb0E\xc6&\xe2\x85:\uab19\x8b\xa0@\xae\x96\x8a\xcf,\xb7\\\xb8\x1e\xad\xf0\xa2aYq\xa2\xef\xb6lΞH\xd5)Ft<\xd6\xc8W\xd1|\xc2\xf7xv\x12\xfc\xef\xeb\xcf\xcf\x1a\xf7\xc31/?\x9e\x94q\x05G\x88X\x93\xe9\xe4\xe2\x941\xb1n6֜\x80\xf2\x9d^\xe0/\x9e\x1a~\v&\x9e\xbcG\xae@\xfbxH+}\x05]\xb9\x10\xe6O\x93\\\x0e)ߩZ\xb9\vl\x1b\x84\x16-2\xb6\xb0y*\x8d\xf1\x89\x18\x879ޭ\x8f\x83\xe2\x15\xc85Q\xb3\xb9\x10\x8a\xbc\n\xd5\xc6\xe2\n8\xa6e\x15-l6\xf4\x8a.lu\xb6ϯ\x92\xb1t\xfc\as=s\xfep\xa5\x81\xd5\xf0\x05\xf7\x17\xb1\xaf\xd1k$¹1\xae\xa0_\x10\xf7,txQ\xef\xde\x1f\xff\xb2\x14\xeb\xf1\xf9\x9c\a\x00H.\xf7\xf6\x84\xba\xf1A8F\x8e\x8eQZc`l\xbf\xcc\x1f\xd0\xf9){|\x11\xe7_\xed]k\xca\xf3\x1f\xfe\xf8\xb3*U\xb1}\x98pH\xf0\xdf\x00\x00\x00\xff\xff{\xd0\xdek}\f\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcYOo\x1b\xbb\x11\xbf\xebS\f\xfc\x0e~\x01\xbc\x12\x92\x16E\xa1ۋ\xddW\xb8}\xcf1\"7\x97 \x87\xd1r\xa4e\xcd%Y\xfe\x91\xa2\x16\xfd\xeeŐ\\I+\xadd9\r\xb2\x17{\xb9\xc3\xe1̏3\xc3\xdfP\xa3\xaa\xaaFh\xe5'r^\x1a=\x05\xb4\x92\xbe\x06\xd2\xfc\xe6\xc7\xcf\u007f\xf6ci&\xab\xb7s\n\xf8v\xf4,\xb5\x98\xc2m\xf4\xc1\xb4\x1fɛ\xe8j\xba\xa3\x85\xd42H\xa3G-\x05\x14\x18p:\x02@\xadM@\x1e\xf6\xfc\nP\x1b\x1d\x9cQ\x8a\\\xb5$=~\x8es\x9aG\xa9\x04\xb9\xb4B\xb7\xfe\xcfQ?k\xb3\xd6oF\x00\xb5\xa3\xa4\xe1I\xb6\xe4\x03\xb6v\n:*5\x02\xd0\xd8\xd2\x14\xac\x11+\xa3bKs\xac\x9f\xa3\xf5\xe3\x15)rf,\xcd\xc8[\xaayݥ3\xd1Na\xf7!\xcf-6e\u007f\x1e\x8d\xf8\x94ԼOj\xd2\x17%}\xf8\xfb\xd0\xd7ߤ\x0fIª\xe8P\x1d\x1b\x91>z\xa9\x97Q\xa1;\xfa<\x02\xf0\xb5\xb14\x85\xab\xab\x11\xc0\n\x95\x14\xc9\xc7l\x90\xb1\xa4\u007fy\xbc\xff\xf4\x87Y\xddP\x8by\x10\xc0:c\xc9\x05\xd9\xd9\xcd\xcfަm\xc7\x00\x04\xf9\xdaI\x9b4\xc25\xab\xca2 x\x9b\xc8Ch\b\n\xd8$\xc0\xa7e\xc0, 4҃#\xebȓ\xce\x1b\xb7\xa7\x16X\x045\x98\xf9?\xa9\x0ec\x98\x91c%\xe0\x1b\x13\x95\xe0\xbd]\x91\v\xe0\xa86K-\xff\xbd\xd5\xec!\x98\xb4\xa4\xc2@\x05\xb8\xee\x91:\x90Ө\x18\x84H7\x80Z@\x8b\x1bp\xc4k@\xd4{ڒ\x88\x1f\xc3\xef\xc6\x11H\xbd0ShB\xb0~:\x99,e\xe8´6m\x1b\xb5\f\x9bI\n69\x8f\xc18?\x11\xb4\"5A+\xabd\xa7NA9n\xc5O\xae\x84\xb0\xbf\xde3,lxw|pR/\xb7\xc3)PN\xc2́\x02\xd2\x03\x96i\xd9\xdc\x1d\x9a<\xc4 |\xfc\xcb\xec\t\xbaE\x13\xe2}\x88\x13\xb8\xbbi~\x873\xe3\"\xf5\x82\\ާ\x853m\xd2HZX#uH/\xb5\x92\xa4\xfb\x18\xfb8oe\xe0\x8d\xfdW$\x1fx;\xc6p\x9br\x13\xe6\x04\xd1\n\f$\xc6p\xaf\xe1\x16[R\xb7\xe8\xe9{\xa3̀\xfa\x8a\x11|\x19\xe7\xfd\n\xd2\x17\xcc\xe0l\x87\xbb\xfc\x1eܐ\x83\x94\x9dY\xaay{\x18#\x9e'\x17\xb2N\x01\x0e\v\xe3\x00\x0f\xc5\xc7{j\x87\x12\x8f\x9f\x9c̳`\x1c.\xe97S\xef\xa5\xf0\t\x9b\xde\x0f\xcd\xe8\xac⒔\x93\x90\x8aj\xf0Y\xf2@%\x80ꦮ\x1br\x94f8\xf2A\xd6\x1c7\xc6\xcb`܆\xd5\xf2|\x12\xe3\x83\xf9\x83\xa0\U000e3360\xb3\xf6?\x18AC\xe6\xf2D\b\r\xe6\x10|4)\x11\\Ԛ\x83\xde\xe8\x8b\r\xb0F\x9c]\xbfhFp\xb4 G\x9a\x13(\x97\x16kR\x01\n(u\x97h\xb9\xe2B0G\xf0\xcd3\xc0$\xa0\xbf\xd1\xe76\x1bNV\xdbAK\u007fy\xbc\xef*l\aR\xb19\x1c\xaex\x16\x11~\x16\x92\x94x\xc4м\xb8\xea\xf5\xfd\"/\x93\nP0\x80`%\xd5\xd4+\xdc \xb5\x0f\x84\"\x0f\x0e\xa8\x04\xe0\xc4uT\xe4or\xb9)UmW\xec\x19k\xc0|z\xc1\xdff\x1f\x1e&\u007f5\xd9\xd6A\x9dX\xd7\xe4Y\r\x06jI\x87\x1b\xf0\xb1n\x00=\xbb \x1d\x89\x19\u007f\x19\xb7\xa8\xe5\x82|\x18\x97\x15\xc8\xf9\xcf\xef\xbe\fa\x06\xf0\xabq@_\xb1\xb5\x8an@f\x94\xb7\xf5\xb3\v\x10\xe93\x10[}\xb0\x96\xa1\x91Î#\aRqx\x9d\x1c\r\xf8L`\x8a\xa3\x91@\xc9g>\xb7\xb9\x84\xec\x99\xf8\x1fΆ\xff^\r\xea\xfc9'\xe9\x15\x8b\\eö'\xe2~\x12\xed\f̙\xe4\xe4rI\x8e\x86\xd1Lu\x9f\v\xec\x1b0\x8e}\xd7fOAR\xcb{\x96\v\x1d\x89#\x83?\xbf\xfbr\xc2\xda>N \xb5\xa0\xaf\xf0\x0e\xa4ΨX#ތ\xe1)E\xc4F\a\xfc\xca\xebԍ\xf1\xa4\xc1h\xb5\x19\xb6\xd6@\x83+\x02oZ\x825)Ue&\"`\x8d\x1b\xf6\xbf\xdb.\x8e0\x04\x8b.\xf4\xb9Ơ֧\x0fw\x1f\xa6\xd9*\x0e\xa1e\xaa\xa4|\xa8-$3\n\xa6\x12\xf9\xa0\xe4\x98Lp\xc4\x1c\x1c\xc1@ݠ\x1e(\xac\x90(IBw\x11Ct4\xbe~m\xb6\x1e\xb2\x84\xee\x19`\v\x87\x85\xe1ǜ\xb9\x17y\x91\xb8\xf5\x8b^<\xec\x85\xefY/\x98\xe8;M\x81\x92#\xc2Ԟ}\xa8\xc9\x06?1+r+I\xeb\xc9ڸg\xa9\x97\x15\xc7]\x957\xdeO\x12Q\x9f\xfc\x94\xfe|\x93\x17\xdeb}\xa1+I\xf4G\xf8\xc3\xeb\xf8ɫ\xdd\xe9X㥇\xd0\xf5\xac\x10\x9dÙ\x9c\x01\xebF\xd6M\xc7\xf8w\xc5r0%Z\x14\xb9¢\xde|\xef(eܢ\xe3\xe57Ui\x0f+Ԃ\xff\xf7\xd2\a\x1e\u007f5PQ^\x90\x82\xff\xb8\xbf\xfb1\xb1\x1b\xe5\xab\x13p\x90\xee\xe6\x10\xb0\xe6^0|\vI\xee,Y\xfa\xd8\x13\xedh\xdb\x00O\xdc\xca\\\xcc\xd3\x02.\x8f\xe8\x11\n\x91.\x00P=\x9e\xa1Pg|\xee\x19\xff\x84K\x0f\xe8\b\x10Z\xb4\xbcOϴ\xa9\xf2\x11lQ\xf2\tʇda#s\x02\xb4VɁò\x1c\xb4\x85\f\x16^\xcd-).\xfd\xb0\xbf\x03\xa8\xe7\xd9g\xd1\xce\xcd\xc3\x109.Kgֱ%\xc8\xc1\xech\xe8q\xfc\x1e\xd1\xd2\x13\xb8qK\xc7\xdciߴj\xb81\xe9I0a\xef\rX#z\xef\xfd8\xeb}\xca\xfe\xbc؛\x05\f\xd1_ܝ%\xe9\x0e\xbd\\\x0fBё\x98\xc0\xb7\xf4g\xb5afؿ;:\xb7\x85\xb7\xc7\xf2\xe92ÉlV\x90-\xc7c\x89\xa15\xfan\x85\xe3\x16\v\xf6\x94\xe5y\xa9̲.\x12\x89\xb81\xa7\\\xa0T$\xa0\xbb\xb8:\x9cs\xa4s_ǜ\x16\\\xaa\xa2U\x06E\xd7\xf2\x14Ӻ\v\x9a'\xeeu\xd3\xe5\xc1\xb5?\xa91z\x12\xa9\a\x1ep\xff\xf04X\x18\xd7b\x98\x82\xc0@ՀB\x1d\x95¹\xa2)\x04\x17\x0f?\x9eL\xfd\x96\xbc\xc7\xe5\xf9\xf4\xfa=\xcb\xe4\xee\xafL\x00\x9c\x9b\x18\xb6\xed_/ů}\x89\x9e\xcb{ρ\x06\xab\x1f\xb2\xc8t\xd8\x17r\xa8T\x9a\xb1\x9fֻ\xcb\xcddϜx[\xfe\xdf\f\a\xb0\r\xfa\xf3\xe0<\xb2\xc4P\xf2lkЙ\xec\x81\xd4\xef\xc5\xf6p\x85\n\x1eh}4v\xaf\x1f\x9dY:\xf2\x87\xa1Qu\xf1s\xe4l\x05\xbf\xa68\xbf\xd8߲\xc0y\x97\x8b\x104Fu\xe9i\x02*б\x9d\x93c\xbf\xe7\x9b@\xbe_\x84\x8f;\xfa\xd4#\xec@ۛ\xdd]\x10d=\xa5\xe5\xa9Q\xa7+3Ι`@Ho\x15\x1e\xf7<\x9d\v\x89Ip\xcapJ\uf8b5KSK.}z\xcd\x1dD\xb2\xe6\xce\xe8AJ\xdb\xe5\xa7\xd4\xe1O\u007f<\xc98\xa4\x0e\xb4\xec\x15\xf5\xf2\x95\x01|\xcf\xfa\xbf\xb7\xee\x93\a\xab\xd7h}c\xc2\xfd\xdd\xd9ݞmź(ߑ\x96T\xbbҭ^\x11궼\u007f\xa4\xe5'\x87\xc1ũ\xe7\x03\xbap\xd9\xe11뉾pn$\xbd$\xc60#\x8b\x0e\xc3q`\xa6\xcb\xdd\xdbß>n\xc0\xcbt\xe9\xc5\xdc'\x93\xa1\xdc\xc8z>N\x98\xda\x19\x97c\xf5Xc\xef \xe8\x15\xfe\xbe\xe9?\xa2\xe6\x0f\xc4\xc3\xc1\xd0\xf6\xa7\xa0\xd5\xdb\xdd[\x8a˪\xfc\xee\x93>\x14\xb7\xc4\xde\xe2\xe5δ\x8c\xech\b\xd6L\xd9I<\x1c\xfe\xf2s\x95/B\xba\x9fr\xd2kmtf\xb3~\n\x9f\xbf\x8c\xa0ܤ~\xea\xec\xe0\xc1\xff\x05\x00\x00\xff\xffx\x8b\xf4\xde6\x1b\x00\x00"), diff --git a/pkg/generated/crds/manifests/velero.io_backupstoragelocations.yaml b/pkg/generated/crds/manifests/velero.io_backupstoragelocations.yaml index 2085c088b1..33a0d1360b 100644 --- a/pkg/generated/crds/manifests/velero.io_backupstoragelocations.yaml +++ b/pkg/generated/crds/manifests/velero.io_backupstoragelocations.yaml @@ -43,6 +43,11 @@ spec: - ReadOnly - ReadWrite type: string + backupSyncPeriod: + description: BackupSyncPeriod defines how frequently to sync backup + API objects from object storage. A value of 0 disables sync. + nullable: true + type: string config: additionalProperties: type: string diff --git a/site/docs/master/api-types/backupstoragelocation.md b/site/docs/master/api-types/backupstoragelocation.md index e77b853615..22473eee1a 100644 --- a/site/docs/master/api-types/backupstoragelocation.md +++ b/site/docs/master/api-types/backupstoragelocation.md @@ -15,6 +15,7 @@ metadata: name: default namespace: velero spec: + backupSyncPeriod: 2m0s provider: aws objectStorage: bucket: myBucket @@ -37,7 +38,7 @@ The configurable parameters are as follows: | `objectStorage/prefix` | String | Optional Field | The directory inside a storage bucket where backups are to be uploaded. | | `config` | map[string]string

(See the corresponding [AWS][0], [GCP][1], and [Azure][2]-specific configs or your provider's documentation.) | None (Optional) | Configuration keys/values to be passed to the cloud provider for backup storage. | | `accessMode` | String | `ReadWrite` | How Velero can access the backup storage location. Valid values are `ReadWrite`, `ReadOnly`. | - +| `backupSyncPeriod` | metav1.Duration | Optional Field | How frequently Velero should synchronize backups in object storage. Default is Velero's server backup sync period. Set this to `0s` to disable sync. | #### AWS