Add Examples section to CLI usage and docs (#1050)

## Description

Adds Examples to CLI usage output and the auto-gen docs

Also cleans up:
* OneDrive flags and flags help
* Addition of OneDrive generated files to docs 


## Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [x] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🐹 Trivial/Minor

## Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* Fixes #529  

## Test Plan

<!-- How will this be tested prior to merging.-->
- [x] 💪 Manual
- [ ]  Unit test
- [ ] 💚 E2E
This commit is contained in:
Georgi Matev 2022-10-05 03:06:32 -04:00 committed by GitHub
parent 3f0951dea2
commit 3a1eb1efd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 190 additions and 65 deletions

View File

@ -34,7 +34,10 @@ const sidebars = {
items: [ items: [
'cli/corso_repo_init_s3', 'cli/corso_repo_connect_s3', 'cli/corso_repo_init_s3', 'cli/corso_repo_connect_s3',
'cli/corso_backup_create_exchange', 'cli/corso_backup_list_exchange', 'cli/corso_backup_details_exchange', 'cli/corso_backup_create_exchange', 'cli/corso_backup_list_exchange', 'cli/corso_backup_details_exchange',
'cli/corso_restore_exchange', 'cli/corso_env' 'cli/corso_restore_exchange',
'cli/corso_backup_create_onedrive', 'cli/corso_backup_list_onedrive', 'cli/corso_backup_details_onedrive',
'cli/corso_restore_onedrive',
'cli/corso_env'
] ]
}, },
{ {

View File

@ -59,11 +59,40 @@ const (
const ( const (
exchangeServiceCommand = "exchange" exchangeServiceCommand = "exchange"
exchangeServiceCommandCreateUseSuffix = " --all | --user <userId or email>" exchangeServiceCommandCreateUseSuffix = " --user <userId or email> | '" + utils.Wildcard + "'"
exchangeServiceCommandDeleteUseSuffix = " --backup <backupId>" exchangeServiceCommandDeleteUseSuffix = " --backup <backupId>"
exchangeServiceCommandDetailsUseSuffix = " --backup <backupId>" exchangeServiceCommandDetailsUseSuffix = " --backup <backupId>"
) )
const (
exchangeServiceCommandCreateExamples = `# Backup all Exchange data for Alice
corso backup create exchange --user alice@example.com
# Backup only Exchange contacts for Alice and Bob
corso backup create exchange --user alice@example.com,bob@example.com --data contacts
# Backup all Exchange data for all M365 users
corso backup create exchange --user '*'`
exchangeServiceCommandDeleteExamples = `# Delete Exchange backup with ID 1234abcd-12ab-cd34-56de-1234abcd
corso backup delete exchange --backup 1234abcd-12ab-cd34-56de-1234abcd`
exchangeServiceCommandDetailsExamples = `# Explore Alice's items in backup 1234abcd-12ab-cd34-56de-1234abcd
corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --user alice@example.com
# Explore Alice's emails with subject containing "Hello world" in folder "Inbox" from a specific backup
corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --email-subject "Hello world" --email-folder Inbox
# Explore Bobs's events occurring after start of 2022 from a specific backup
corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user bob@example.com --event-starts-after 2022-01-01T00:00:00
# Explore Alice's contacts with name containing Andy from a specific backup
corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --contact-name Andy`
)
// called by backup.go to map parent subcommands to provider-specific handling. // called by backup.go to map parent subcommands to provider-specific handling.
func addExchangeCommands(parent *cobra.Command) *cobra.Command { func addExchangeCommands(parent *cobra.Command) *cobra.Command {
var ( var (
@ -76,6 +105,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
c, fs = utils.AddCommand(parent, exchangeCreateCmd()) c, fs = utils.AddCommand(parent, exchangeCreateCmd())
c.Use = c.Use + exchangeServiceCommandCreateUseSuffix c.Use = c.Use + exchangeServiceCommandCreateUseSuffix
c.Example = utils.IndentExamples(exchangeServiceCommandCreateExamples)
// Flags addition ordering should follow the order we want them to appear in help and docs: // Flags addition ordering should follow the order we want them to appear in help and docs:
// More generic (ex: --all) and more frequently used flags take precedence. // More generic (ex: --all) and more frequently used flags take precedence.
@ -85,7 +115,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar( fs.StringSliceVar(
&user, &user,
"user", nil, "user", nil,
"Backup Exchange data by user ID; accepts "+utils.Wildcard+" to select all users") "Backup Exchange data by user ID; accepts '"+utils.Wildcard+"' to select all users")
fs.StringSliceVar( fs.StringSliceVar(
&exchangeData, &exchangeData,
"data", nil, "data", nil,
@ -99,6 +129,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
c, fs = utils.AddCommand(parent, exchangeDetailsCmd()) c, fs = utils.AddCommand(parent, exchangeDetailsCmd())
c.Use = c.Use + exchangeServiceCommandDetailsUseSuffix c.Use = c.Use + exchangeServiceCommandDetailsUseSuffix
c.Example = utils.IndentExamples(exchangeServiceCommandDetailsExamples)
// Flags addition ordering should follow the order we want them to appear in help and docs: // Flags addition ordering should follow the order we want them to appear in help and docs:
// More generic (ex: --all) and more frequently used flags take precedence. // More generic (ex: --all) and more frequently used flags take precedence.
@ -109,17 +140,17 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar( fs.StringSliceVar(
&user, &user,
"user", nil, "user", nil,
"Select backup details by user ID; accepts "+utils.Wildcard+" to select all users.") "Select backup details by user ID; accepts '"+utils.Wildcard+"' to select all users.")
// email flags // email flags
fs.StringSliceVar( fs.StringSliceVar(
&email, &email,
"email", nil, "email", nil,
"Select backup details for emails by email ID; accepts "+utils.Wildcard+" to select all emails.") "Select backup details for emails by email ID; accepts '"+utils.Wildcard+"' to select all emails.")
fs.StringSliceVar( fs.StringSliceVar(
&emailFolder, &emailFolder,
"email-folder", nil, "email-folder", nil,
"Select backup details for emails within a folder; accepts "+utils.Wildcard+" to select all email folders.") "Select backup details for emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
fs.StringVar( fs.StringVar(
&emailSubject, &emailSubject,
"email-subject", "", "email-subject", "",
@ -141,11 +172,11 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar( fs.StringSliceVar(
&event, &event,
"event", nil, "event", nil,
"Select backup details for events by event ID; accepts "+utils.Wildcard+" to select all events.") "Select backup details for events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
fs.StringSliceVar( fs.StringSliceVar(
&eventCalendar, &eventCalendar,
"event-calendar", nil, "event-calendar", nil,
"Select backup details for events under a calendar; accepts "+utils.Wildcard+" to select all events.") "Select backup details for events under a calendar; accepts '"+utils.Wildcard+"' to select all events.")
fs.StringVar( fs.StringVar(
&eventSubject, &eventSubject,
"event-subject", "", "event-subject", "",
@ -171,11 +202,11 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar( fs.StringSliceVar(
&contact, &contact,
"contact", nil, "contact", nil,
"Select backup details for contacts by contact ID; accepts "+utils.Wildcard+" to select all contacts.") "Select backup details for contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
fs.StringSliceVar( fs.StringSliceVar(
&contactFolder, &contactFolder,
"contact-folder", nil, "contact-folder", nil,
"Select backup details for contacts within a folder; accepts "+utils.Wildcard+" to select all contact folders.") "Select backup details for contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
fs.StringVar( fs.StringVar(
&contactName, &contactName,
@ -186,6 +217,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
c, fs = utils.AddCommand(parent, exchangeDeleteCmd()) c, fs = utils.AddCommand(parent, exchangeDeleteCmd())
c.Use = c.Use + exchangeServiceCommandDeleteUseSuffix c.Use = c.Use + exchangeServiceCommandDeleteUseSuffix
c.Example = utils.IndentExamples(exchangeServiceCommandDeleteExamples)
fs.StringVar(&backupID, "backup", "", "ID of the backup to delete. (required)") fs.StringVar(&backupID, "backup", "", "ID of the backup to delete. (required)")
cobra.CheckErr(c.MarkFlagRequired("backup")) cobra.CheckErr(c.MarkFlagRequired("backup"))

View File

@ -25,11 +25,36 @@ import (
const ( const (
oneDriveServiceCommand = "onedrive" oneDriveServiceCommand = "onedrive"
oneDriveServiceCommandCreateUseSuffix = " --user <userId or email> | " + utils.Wildcard oneDriveServiceCommandCreateUseSuffix = " --user <userId or email> | '" + utils.Wildcard + "'"
oneDriveServiceCommandDeleteUseSuffix = " --backup <backupId>" oneDriveServiceCommandDeleteUseSuffix = " --backup <backupId>"
oneDriveServiceCommandDetailsUseSuffix = " --backup <backupId>" oneDriveServiceCommandDetailsUseSuffix = " --backup <backupId>"
) )
const (
oneDriveServiceCommandCreateExamples = `# Backup OneDrive data for Alice
corso backup create onedrive --user alice@example.com
# Backup OneDrive for Alice and Bob
corso backup create onedrive --user alice@example.com,bob@example.com
# Backup all OneDrive data for all M365 users
corso backup create onedrive --user '*'`
oneDriveServiceCommandDeleteExamples = `# Delete OneDrive backup with ID 1234abcd-12ab-cd34-56de-1234abcd
corso backup delete onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd`
oneDriveServiceCommandDetailsExamples = `# Explore Alice's files from backup 1234abcd-12ab-cd34-56de-1234abcd
corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd --user alice@example.com
# Explore Alice or Bob's files with name containing "Fiscal 22" in folder "Reports"
corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com,bob@example.com --file-name "Fiscal 22" --folder "Reports"
# Explore Alice's files created before end of 2015 from a specific backup
corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --file-created-before 2015-01-01T00:00:00`
)
var ( var (
folderPaths []string folderPaths []string
fileNames []string fileNames []string
@ -52,9 +77,10 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
c, fs = utils.AddCommand(parent, oneDriveCreateCmd()) c, fs = utils.AddCommand(parent, oneDriveCreateCmd())
c.Use = c.Use + oneDriveServiceCommandCreateUseSuffix c.Use = c.Use + oneDriveServiceCommandCreateUseSuffix
c.Example = utils.IndentExamples(oneDriveServiceCommandCreateExamples)
fs.StringArrayVar(&user, "user", nil, fs.StringArrayVar(&user, "user", nil,
"Backup OneDrive data by user ID; accepts "+utils.Wildcard+" to select all users. (required)") "Backup OneDrive data by user ID; accepts '"+utils.Wildcard+"' to select all users. (required)")
options.AddOperationFlags(c) options.AddOperationFlags(c)
case listCommand: case listCommand:
@ -64,6 +90,7 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
c, fs = utils.AddCommand(parent, oneDriveDetailsCmd()) c, fs = utils.AddCommand(parent, oneDriveDetailsCmd())
c.Use = c.Use + oneDriveServiceCommandDetailsUseSuffix c.Use = c.Use + oneDriveServiceCommandDetailsUseSuffix
c.Example = utils.IndentExamples(oneDriveServiceCommandDetailsExamples)
fs.StringVar(&backupID, "backup", "", "ID of the backup to explore. (required)") fs.StringVar(&backupID, "backup", "", "ID of the backup to explore. (required)")
cobra.CheckErr(c.MarkFlagRequired("backup")) cobra.CheckErr(c.MarkFlagRequired("backup"))
@ -73,37 +100,38 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar( fs.StringSliceVar(
&folderPaths, &folderPaths,
"folder", nil, "folder", nil,
"Select backup details by OneDrive folder; defaults to root") "Select backup details by OneDrive folder; defaults to root.")
fs.StringSliceVar( fs.StringSliceVar(
&fileNames, &fileNames,
"file-name", nil, "file", nil,
"Select backup details by OneDrive file name") "Select backup details by file name or ID.")
// onedrive info flags // onedrive info flags
fs.StringVar( fs.StringVar(
&fileCreatedAfter, &fileCreatedAfter,
"file-created-after", "", "file-created-after", "",
"Select files created after this datetime") "Select backup details for files created after this datetime.")
fs.StringVar( fs.StringVar(
&fileCreatedBefore, &fileCreatedBefore,
"file-created-before", "", "file-created-before", "",
"Select files created before this datetime") "Select backup details for files created before this datetime.")
fs.StringVar( fs.StringVar(
&fileModifiedAfter, &fileModifiedAfter,
"file-modified-after", "", "file-modified-after", "",
"Select files modified after this datetime") "Select backup details for files modified after this datetime.")
fs.StringVar( fs.StringVar(
&fileModifiedBefore, &fileModifiedBefore,
"file-modified-before", "", "file-modified-before", "",
"Select files modified before this datetime") "Select backup details for files modified before this datetime.")
case deleteCommand: case deleteCommand:
c, fs = utils.AddCommand(parent, oneDriveDeleteCmd()) c, fs = utils.AddCommand(parent, oneDriveDeleteCmd())
c.Use = c.Use + oneDriveServiceCommandDeleteUseSuffix c.Use = c.Use + oneDriveServiceCommandDeleteUseSuffix
c.Example = utils.IndentExamples(oneDriveServiceCommandDeleteExamples)
fs.StringVar(&backupID, "backup", "", "ID of the backup to delete. (required)") fs.StringVar(&backupID, "backup", "", "ID of the backup to delete. (required)")
cobra.CheckErr(c.MarkFlagRequired("backup")) cobra.CheckErr(c.MarkFlagRequired("backup"))
@ -119,10 +147,11 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
// `corso backup create onedrive [<flag>...]` // `corso backup create onedrive [<flag>...]`
func oneDriveCreateCmd() *cobra.Command { func oneDriveCreateCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: oneDriveServiceCommand, Use: oneDriveServiceCommand,
Short: "Backup M365 OneDrive service data", Short: "Backup M365 OneDrive service data",
RunE: createOneDriveCmd, RunE: createOneDriveCmd,
Args: cobra.NoArgs, Args: cobra.NoArgs,
Example: oneDriveServiceCommandCreateExamples,
} }
} }
@ -234,10 +263,11 @@ func listOneDriveCmd(cmd *cobra.Command, args []string) error {
// `corso backup details onedrive [<flag>...]` // `corso backup details onedrive [<flag>...]`
func oneDriveDetailsCmd() *cobra.Command { func oneDriveDetailsCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: oneDriveServiceCommand, Use: oneDriveServiceCommand,
Short: "Shows the details of a M365 OneDrive service backup", Short: "Shows the details of a M365 OneDrive service backup",
RunE: detailsOneDriveCmd, RunE: detailsOneDriveCmd,
Args: cobra.NoArgs, Args: cobra.NoArgs,
Example: oneDriveServiceCommandDetailsExamples,
} }
} }
@ -318,10 +348,11 @@ func runDetailsOneDriveCmd(
// `corso backup delete onedrive [<flag>...]` // `corso backup delete onedrive [<flag>...]`
func oneDriveDeleteCmd() *cobra.Command { func oneDriveDeleteCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: oneDriveServiceCommand, Use: oneDriveServiceCommand,
Short: "Delete backed-up M365 OneDrive service data", Short: "Delete backed-up M365 OneDrive service data",
RunE: deleteOneDriveCmd, RunE: deleteOneDriveCmd,
Args: cobra.NoArgs, Args: cobra.NoArgs,
Example: oneDriveServiceCommandDeleteExamples,
} }
} }

View File

@ -58,6 +58,26 @@ const (
s3ProviderCommandUseSuffix = " --bucket <bucket>" s3ProviderCommandUseSuffix = " --bucket <bucket>"
) )
const (
s3ProviderCommandInitExamples = `# Create a new Corso repo in AWS S3 bucket named "my-bucket"
corso repo init s3 --bucket my-bucket
# Create a new Corso repo in AWS S3 bucket named "my-bucket" using a prefix
corso repo init s3 --bucket my-bucket --prefix my-prefix
# Create a new Corso repo in an S3 compliant storage provider
corso repo init s3 --bucket my-bucket --endpoint https://my-s3-server-endpoint`
s3ProviderCommandConnectExamples = `# Connect to a Corso repo in AWS S3 bucket named "my-bucket"
corso repo connect s3 --bucket my-bucket
# Connect to a Corso repo in AWS S3 bucket named "my-bucket" using a prefix
corso repo connect s3 --bucket my-bucket --prefix my-prefix
# Connect to a Corso repo in an S3 compliant storage provider
corso repo connect s3 --bucket my-bucket --endpoint https://my-s3-server-endpoint`
)
// --------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------
// Init // Init
// --------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------
@ -65,11 +85,12 @@ const (
// `corso repo init s3 [<flag>...]` // `corso repo init s3 [<flag>...]`
func s3InitCmd() *cobra.Command { func s3InitCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: s3ProviderCommand, Use: s3ProviderCommand,
Short: "Initialize a S3 repository", Short: "Initialize a S3 repository",
Long: `Bootstraps a new S3 repository and connects it to your m356 account.`, Long: `Bootstraps a new S3 repository and connects it to your m356 account.`,
RunE: initS3Cmd, RunE: initS3Cmd,
Args: cobra.NoArgs, Args: cobra.NoArgs,
Example: utils.IndentExamples(s3ProviderCommandInitExamples),
} }
} }
@ -123,11 +144,12 @@ func initS3Cmd(cmd *cobra.Command, args []string) error {
// `corso repo connect s3 [<flag>...]` // `corso repo connect s3 [<flag>...]`
func s3ConnectCmd() *cobra.Command { func s3ConnectCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: s3ProviderCommand, Use: s3ProviderCommand,
Short: "Connect to a S3 repository", Short: "Connect to a S3 repository",
Long: `Ensures a connection to an existing S3 repository.`, Long: `Ensures a connection to an existing S3 repository.`,
RunE: connectS3Cmd, RunE: connectS3Cmd,
Args: cobra.NoArgs, Args: cobra.NoArgs,
Example: s3ProviderCommandConnectExamples,
} }
} }

View File

@ -61,16 +61,16 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar(&user, fs.StringSliceVar(&user,
"user", nil, "user", nil,
"Restore data by user ID; accepts "+utils.Wildcard+" to select all users.") "Restore data by user ID; accepts '"+utils.Wildcard+"' to select all users.")
// email flags // email flags
fs.StringSliceVar(&email, fs.StringSliceVar(&email,
"email", nil, "email", nil,
"Restore emails by ID; accepts "+utils.Wildcard+" to select all emails.") "Restore emails by ID; accepts '"+utils.Wildcard+"' to select all emails.")
fs.StringSliceVar( fs.StringSliceVar(
&emailFolder, &emailFolder,
"email-folder", nil, "email-folder", nil,
"Restore emails within a folder; accepts "+utils.Wildcard+" to select all email folders.") "Restore emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
fs.StringVar( fs.StringVar(
&emailSubject, &emailSubject,
"email-subject", "", "email-subject", "",
@ -91,11 +91,11 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
// event flags // event flags
fs.StringSliceVar(&event, fs.StringSliceVar(&event,
"event", nil, "event", nil,
"Restore events by event ID; accepts "+utils.Wildcard+" to select all events.") "Restore events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
fs.StringSliceVar( fs.StringSliceVar(
&eventCalendar, &eventCalendar,
"event-calendar", nil, "event-calendar", nil,
"Restore events under a calendar; accepts "+utils.Wildcard+" to select all event calendars.") "Restore events under a calendar; accepts '"+utils.Wildcard+"' to select all event calendars.")
fs.StringVar( fs.StringVar(
&eventSubject, &eventSubject,
"event-subject", "", "event-subject", "",
@ -121,11 +121,11 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar( fs.StringSliceVar(
&contact, &contact,
"contact", nil, "contact", nil,
"Restore contacts by contact ID; accepts "+utils.Wildcard+" to select all contacts.") "Restore contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
fs.StringSliceVar( fs.StringSliceVar(
&contactFolder, &contactFolder,
"contact-folder", nil, "contact-folder", nil,
"Restore contacts within a folder; accepts "+utils.Wildcard+" to select all contact folders.") "Restore contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
fs.StringVar( fs.StringVar(
&contactName, &contactName,
"contact-name", "", "contact-name", "",
@ -141,15 +141,30 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
const ( const (
exchangeServiceCommand = "exchange" exchangeServiceCommand = "exchange"
exchangeServiceCommandUseSuffix = " --backup <backupId>" exchangeServiceCommandUseSuffix = " --backup <backupId>"
exchangeServiceCommandRestoreExamples = `# Restore emails with ID 98765abcdef and 12345abcdef from a specific backup
corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --email 98765abcdef,12345abcdef
# Restore Alice's emails with subject containing "Hello world" in "Inbox" from a specific backup
corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --email-subject "Hello world" --email-folder Inbox
# Restore Bobs's entire calendar from a specific backup
corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user bob@example.com --event-calendar Calendar
# Restore contact with ID abdef0101 from a specific backup
corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --contact abdef0101`
) )
// `corso restore exchange [<flag>...]` // `corso restore exchange [<flag>...]`
func exchangeRestoreCmd() *cobra.Command { func exchangeRestoreCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: exchangeServiceCommand, Use: exchangeServiceCommand,
Short: "Restore M365 Exchange service data", Short: "Restore M365 Exchange service data",
RunE: restoreExchangeCmd, RunE: restoreExchangeCmd,
Args: cobra.NoArgs, Args: cobra.NoArgs,
Example: utils.IndentExamples(exchangeServiceCommandRestoreExamples),
} }
} }

View File

@ -47,7 +47,7 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar(&user, fs.StringSliceVar(&user,
"user", nil, "user", nil,
"Restore data by user ID; accepts "+utils.Wildcard+" to select all users.") "Restore data by user ID; accepts '"+utils.Wildcard+"' to select all users.")
// onedrive hierarchy (path/name) flags // onedrive hierarchy (path/name) flags
@ -58,8 +58,8 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
fs.StringSliceVar( fs.StringSliceVar(
&fileNames, &fileNames,
"file-name", nil, "file", nil,
"Restore items by OneDrive file name") "Restore items by file name or ID")
// onedrive info flags // onedrive info flags
@ -91,15 +91,27 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
const ( const (
oneDriveServiceCommand = "onedrive" oneDriveServiceCommand = "onedrive"
oneDriveServiceCommandUseSuffix = " --backup <backupId>" oneDriveServiceCommandUseSuffix = " --backup <backupId>"
oneDriveServiceCommandRestoreExamples = `# Restore file with ID 98765abcdef
corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd --file 98765abcdef
# Restore Alice's file named "FY2021 Planning.xlsx in "Documents/Finance Reports" from a specific backup
corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --file "FY2021 Planning.xlsx" --folder "Documents/Finance Reports"
# Restore all files from Bob's folder that were created before 2020 when captured in a specific backup
corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd
--user bob@example.com --folder "Documents/Finance Reports" --file-created-before 2020-01-01T00:00:00`
) )
// `corso restore onedrive [<flag>...]` // `corso restore onedrive [<flag>...]`
func oneDriveRestoreCmd() *cobra.Command { func oneDriveRestoreCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: oneDriveServiceCommand, Use: oneDriveServiceCommand,
Short: "Restore M365 OneDrive service data", Short: "Restore M365 OneDrive service data",
RunE: restoreOneDriveCmd, RunE: restoreOneDriveCmd,
Args: cobra.NoArgs, Args: cobra.NoArgs,
Example: utils.IndentExamples(oneDriveServiceCommandRestoreExamples),
} }
} }

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"regexp"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -57,3 +58,12 @@ func AddCommand(parent, c *cobra.Command) (*cobra.Command, *pflag.FlagSet) {
return c, c.Flags() return c, c.Flags()
} }
// Takes in a multi-line string and returns it indented by 2 spaces.
// This is only to be used with Examples strings which the default usage
// template does not properly indent to match other sections
func IndentExamples(examples string) string {
e := regexp.MustCompile(`(?m)^`)
return e.ReplaceAllString(examples, " ")
}

View File

@ -138,7 +138,12 @@ func genMarkdownCustomCorso(cmd *cobra.Command, w io.Writer) error {
} }
if cmd.Runnable() { if cmd.Runnable() {
buf.WriteString(fmt.Sprintf("```bash\n%s\n```\n", cmd.UseLine())) buf.WriteString(fmt.Sprintf("```bash\n%s\n```\n\n", cmd.UseLine()))
}
if cmd.HasExample() {
buf.WriteString("### Examples\n\n")
buf.WriteString(fmt.Sprintf("```bash\n%s\n```\n", cmd.Example))
} }
flags := cmd.NonInheritedFlags() flags := cmd.NonInheritedFlags()
@ -155,11 +160,6 @@ func genMarkdownCustomCorso(cmd *cobra.Command, w io.Writer) error {
printFlags(buf, parentFlags) printFlags(buf, parentFlags)
} }
if len(cmd.Example) > 0 {
buf.WriteString("\n### Examples\n\n")
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example))
}
_, err := buf.WriteTo(w) _, err := buf.WriteTo(w)
return err return err