public cli and docs for intial advanced restore (#3769)
creates public docs and un-hides the advanced restore option cli flags. --- #### Does this PR need a docs update or release note? - [x] ✅ Yes, it's included #### Type of change - [x] 🌻 Feature #### Issue(s) * #3562
This commit is contained in:
parent
5a78f478a1
commit
0ec922577d
@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Drive items backup and restore link shares
|
- Drive items backup and restore link shares
|
||||||
|
- Restore commands now accept an optional top-level restore destination with the `--destination` flag. Setting the destination to '/' will restore items back into their original location.
|
||||||
|
- Restore commands can specify item collision behavior. Options are Skip (default), Replace, and Copy.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Return a ServiceNotEnabled error when a tenant has no active SharePoint license.
|
- Return a ServiceNotEnabled error when a tenant has no active SharePoint license.
|
||||||
|
|||||||
@ -21,10 +21,9 @@ func AddRestoreConfigFlags(cmd *cobra.Command) {
|
|||||||
fs := cmd.Flags()
|
fs := cmd.Flags()
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&CollisionsFV, CollisionsFN, string(control.Skip),
|
&CollisionsFV, CollisionsFN, string(control.Skip),
|
||||||
"How to handle item collisions: "+string(control.Skip)+", "+string(control.Copy)+", or "+string(control.Replace))
|
//nolint:lll
|
||||||
cobra.CheckErr(fs.MarkHidden(CollisionsFN))
|
"Sets the behavior for existing item collisions: "+string(control.Skip)+", "+string(control.Copy)+", or "+string(control.Replace))
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&DestinationFV, DestinationFN, "",
|
&DestinationFV, DestinationFN, "",
|
||||||
"Overrides the destination where items get restored. '/' places items back in their original location.")
|
"Overrides the destination where items get restored; '/' places items into their original location")
|
||||||
cobra.CheckErr(fs.MarkHidden(DestinationFN))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,15 +34,46 @@ func AddCommands(cmd *cobra.Command) {
|
|||||||
|
|
||||||
const restoreCommand = "restore"
|
const restoreCommand = "restore"
|
||||||
|
|
||||||
|
// FIXME: this command doesn't build docs, and so these examples
|
||||||
|
// are not visible within the website.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
|
const restoreCommandExamples = `# Restore email inbox messages to their original location
|
||||||
|
corso restore exchange \
|
||||||
|
--backup 1234abcd-12ab-cd34-56de-1234abcd \
|
||||||
|
--email-folder '/inbox' \
|
||||||
|
--destination '/'
|
||||||
|
|
||||||
|
# Restore a specific OneDrive folder to the top-level destination named "recovered_june_releases"
|
||||||
|
corso restore onedrive \
|
||||||
|
--backup 1234abcd-12ab-cd34-56de-1234abcd \
|
||||||
|
--folder '/work/corso_june_releases' \
|
||||||
|
--destination /recovered_june_releases
|
||||||
|
|
||||||
|
# Restore a calendar event, making a copy if the event already exists.
|
||||||
|
corso restore exchange \
|
||||||
|
--backup 1234abcd-12ab-cd34-56de-1234abcd \
|
||||||
|
--event-calendar 'Company Events' \
|
||||||
|
--event abdef0101 \
|
||||||
|
--collisions copy
|
||||||
|
|
||||||
|
# Restore a SharePoint library in-place, replacing any conflicting files.
|
||||||
|
corso restore sharepoint \
|
||||||
|
--backup 1234abcd-12ab-cd34-56de-1234abcd \
|
||||||
|
--library documents \
|
||||||
|
--destination '/' \
|
||||||
|
--collisions replace`
|
||||||
|
|
||||||
// The restore category of commands.
|
// The restore category of commands.
|
||||||
// `corso restore [<subcommand>] [<flag>...]`
|
// `corso restore [<subcommand>] [<flag>...]`
|
||||||
func restoreCmd() *cobra.Command {
|
func restoreCmd() *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: restoreCommand,
|
Use: restoreCommand,
|
||||||
Short: "Restore your service data",
|
Short: "Restore your service data",
|
||||||
Long: `Restore the data stored in one of your M365 services.`,
|
Long: `Restore the data stored in one of your M365 services.`,
|
||||||
RunE: handleRestoreCmd,
|
RunE: handleRestoreCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
|
Example: restoreCommandExamples,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -281,9 +281,63 @@ A confirmation of the recovered email will be shown and the email will appear in
|
|||||||
360bf6840396 phish@contoso.info Re: Request for Apple/Amazon gift cards 2022-10-18T02:27:47Z
|
360bf6840396 phish@contoso.info Re: Request for Apple/Amazon gift cards 2022-10-18T02:27:47Z
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Advanced Restores
|
||||||
|
|
||||||
|
You can control where your data gets restored, and what happens if restored items would overwrite existing
|
||||||
|
ones. Let's restore a folder in OneDrive back to its original location. Since the folder already exists, we can
|
||||||
|
tell corso to with duplicate names as copies.
|
||||||
|
|
||||||
|
<Tabs groupId="os">
|
||||||
|
<TabItem value="win" label="Powershell">
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Restore a folder to its original location
|
||||||
|
.\corso restore onedrive --backup <id of your selected backup> `
|
||||||
|
--folder "/presentations/company_culture" `
|
||||||
|
--destination "/" `
|
||||||
|
--collisions copy
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="unix" label="Linux/macOS">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Restore a folder to its original location
|
||||||
|
./corso restore onedrive --backup <id of your selected backup> \
|
||||||
|
--folder "/presentations/company_culture" \
|
||||||
|
--destination "/" \
|
||||||
|
--collisions copy
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="docker" label="Docker">
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{
|
||||||
|
`# Restore a folder to its original location
|
||||||
|
docker run --env-file $HOME/.corso/corso.env \\
|
||||||
|
--volume $HOME/.corso:/app/corso ghcr.io/alcionai/corso:${Version()} \\
|
||||||
|
restore exchange --backup <id of your selected backup> \\
|
||||||
|
--email <email message ID> --folder '/presentations/company_culture' \\
|
||||||
|
--destination '/' --collisions copy`
|
||||||
|
}</CodeBlock>
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
A confirmation of the recovered files will be shown and those files will appear back in their original folder.
|
||||||
|
|
||||||
|
```text
|
||||||
|
ID ItemName ParentPath Size Owner Created Modified
|
||||||
|
f43bff59de56 slides 1.ppt /presentations/company_culture 23 kB 2023-07-05T18:37:57Z 2023-07-05T18:37:58Z
|
||||||
|
c0de2282e9c7 giftcards.xls /presentations/company_culture 0 B 2023-07-05T18:37:47Z 2023-07-05T18:37:47Z
|
||||||
|
```
|
||||||
|
|
||||||
|
See [here](../setup/restore-options) for more restoration options.
|
||||||
|
|
||||||
## Read more
|
## Read more
|
||||||
|
|
||||||
The above tutorial only scratches the surface for Corso's capabilities. We encourage you to dig deeper by:
|
The above tutorial only scratches the surface for Corso's capabilities. We encourage you to dig deeper by:
|
||||||
|
|
||||||
* Learning about [Corso concepts and setup](../setup/concepts)
|
* Learning about [Corso concepts and setup](../setup/concepts)
|
||||||
* Explore Corso backup and restore options for Exchange and Onedrive in the [Command Line Reference](../cli/corso)
|
* Explore Corso backup and restore options for Exchange and Onedrive in the [Command Line Reference](../cli/corso)
|
||||||
|
* Leverage Corso's [Advanced Restoration Options](../setup/restore-options)
|
||||||
|
|||||||
110
website/docs/setup/restore-options.md
Normal file
110
website/docs/setup/restore-options.md
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# Restore Options
|
||||||
|
|
||||||
|
import CodeBlock from '@theme/CodeBlock';
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
import {Version} from '@site/src/corsoEnv';
|
||||||
|
|
||||||
|
The default restore command is an great way to restore data in a non-destructive
|
||||||
|
manner to a new folder. When you need more control over the results you can
|
||||||
|
use the advanced configuration options to change where and how your data
|
||||||
|
gets restored.
|
||||||
|
|
||||||
|
## Destination
|
||||||
|
|
||||||
|
The `--destination` flag lets you select the top-level folder where Corso will
|
||||||
|
write all of the restored data.
|
||||||
|
|
||||||
|
### The default destination
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{
|
||||||
|
`corso restore onedrive --backup abcd`
|
||||||
|
}</CodeBlock>
|
||||||
|
|
||||||
|
If the flag isn't provided, Corso will create a new folder with a standard name:
|
||||||
|
`Corso_Restore_<current-date-time>`. The default restore folder is always newly
|
||||||
|
created, and can't interfere with any existing items. If you're concerned about
|
||||||
|
data integrity then this is always the safest option.
|
||||||
|
|
||||||
|
### An alternate destination
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{
|
||||||
|
`corso restore onedrive --backup abcd --destination /my-latest-restore`
|
||||||
|
}</CodeBlock>
|
||||||
|
|
||||||
|
When a destination is manually specified, all restored will appear in that top-level
|
||||||
|
folder. In the example above, Corso will restore everything into `my-latest-restore`.
|
||||||
|
If that folder doesn't already exist, Corso will automatically create it. If it does
|
||||||
|
exist, the restore will use the existing folder, allowing you to restore to the same
|
||||||
|
folder multiple times.
|
||||||
|
|
||||||
|
### The original location
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{
|
||||||
|
`corso restore onedrive --backup abcd --destination /`
|
||||||
|
}</CodeBlock>
|
||||||
|
|
||||||
|
You can restore items back to their original location by setting the destination
|
||||||
|
to `/`. This skips the creation of a top-level folder, and all restored items will
|
||||||
|
appear back in their location at the time of backup.
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
* Destination won't create N-depth folder structures. `--destination a/b/c`
|
||||||
|
doesn't create three folders; it creates a single, top-level folder named `a/b/c`.
|
||||||
|
|
||||||
|
* Exchange Calendars don't support folder hierarchy. If your backup contains the
|
||||||
|
calendars `MyCalendar` and `Birthdays`, and you restore to `--destination Restored`,
|
||||||
|
all of the restored calendar events will appear in the `Restored` calendar. However,
|
||||||
|
if you restore events in-place (`--destination /`) then all events will return to
|
||||||
|
their original calendars.
|
||||||
|
|
||||||
|
* When restoring Exchange Calendar Events to a destination folder, Events that were
|
||||||
|
safe in different calendars may collide with each other in the destination calendar.
|
||||||
|
|
||||||
|
## Item collision handling
|
||||||
|
|
||||||
|
When restoring data into an existing folder, the items restored may conflict
|
||||||
|
with existing data. When this happens, Corso resolves the conflict using its
|
||||||
|
collision configuration.
|
||||||
|
|
||||||
|
Collision detection differs between each service and type of data. The general
|
||||||
|
comparison always follows the same pattern: "within the current folder, if the
|
||||||
|
restore item looks identical to an existing item, it collides."
|
||||||
|
|
||||||
|
The comparison uses item metadata (names, subjects, titles, etc), not item content.
|
||||||
|
If the current `reports.txt` has different contents than the backup `reports.txt`,
|
||||||
|
it still collides.
|
||||||
|
|
||||||
|
Collisions can be handled with three different configurations: `Skip`, `Copy`,
|
||||||
|
and `Replace`.
|
||||||
|
|
||||||
|
## Skip (default)
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{
|
||||||
|
`corso restore onedrive --backup abcd --collisions skip --destination /`
|
||||||
|
}</CodeBlock>
|
||||||
|
|
||||||
|
When a collision is identified, the item is skipped and
|
||||||
|
no restore is attempted.
|
||||||
|
|
||||||
|
## Copy
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{
|
||||||
|
`corso restore onedrive --backup abcd --collisions copy --destination /my-latest-restore`
|
||||||
|
}</CodeBlock>
|
||||||
|
|
||||||
|
Item collisions create a copy of the item in the backup. The copy holds the backup
|
||||||
|
version of the item, leaving the current version unchanged. If necessary, changes
|
||||||
|
item properties (such as filenames) to avoid additional collisions. Eg:
|
||||||
|
the copy of`reports.txt` is named `reports 1.txt`.
|
||||||
|
|
||||||
|
## Replace
|
||||||
|
|
||||||
|
<CodeBlock language="bash">{
|
||||||
|
`corso restore onedrive --backup abcd --collisions replace --destination /`
|
||||||
|
}</CodeBlock>
|
||||||
|
|
||||||
|
Collisions will entirely replace the current version of the item with the backup
|
||||||
|
version. If multiple existing items collide with the backup item, only one of the
|
||||||
|
existing items is replaced.
|
||||||
@ -8,26 +8,22 @@ Below is a list of known Corso issues and limitations:
|
|||||||
* Backups of Exchange email may not include changes to the read status of an email if no other changes
|
* Backups of Exchange email may not include changes to the read status of an email if no other changes
|
||||||
to the email have been made since the previous backup.
|
to the email have been made since the previous backup.
|
||||||
|
|
||||||
* Restores are non-destructive to a dedicated restore folder in the original Exchange mailbox or OneDrive account.
|
|
||||||
Advanced restore options such as in-place restore, or restore to a specific folder or to a different account aren't
|
|
||||||
yet supported.
|
|
||||||
|
|
||||||
* Restoration of Nested attachments within Exchange Mail or Calendars aren't yet supported.
|
* Restoration of Nested attachments within Exchange Mail or Calendars aren't yet supported.
|
||||||
|
|
||||||
* Folders and Calendars containing zero items or subfolders aren't included in the backup.
|
* Folders and Calendars containing zero items or subfolders aren't included in the backup.
|
||||||
|
|
||||||
* Provides no guarantees about whether data moved, added, or deleted in M365
|
* Provides no guarantees the inclusion of data that's moved, added, or deleted
|
||||||
while a backup is being created will be included in the running backup.
|
from M365 while a backup creation is running.
|
||||||
Future backups run when the data isn't modified will include the data.
|
The next backup creation will correct any missing data.
|
||||||
|
|
||||||
* SharePoint document library data can't be restored after the library has been deleted.
|
* SharePoint document library data can't be restored after the library has been deleted.
|
||||||
|
|
||||||
* Sharing information of items in OneDrive/SharePoint using sharing links aren't backed up and restored.
|
* Sharing information of items in OneDrive/SharePoint using sharing links aren't backed up and restored.
|
||||||
|
|
||||||
* Permissions/Access given to a site group can't be restored
|
* Permissions/Access given to a site group can't be restored.
|
||||||
|
|
||||||
* If a link share is created for an item with inheritance disabled
|
* If a link share is created for an item with inheritance disabled
|
||||||
(via the Graph API), the link shares restored in that item will
|
(via the Graph API), the link shares restored in that item will
|
||||||
not be inheritable by children
|
not be inheritable by children.
|
||||||
|
|
||||||
* Link shares with password protection can't be restored
|
* Link shares with password protection can't be restored.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user