github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/cmd/mattermost/commands/integrity.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package commands 5 6 import ( 7 "fmt" 8 "os" 9 "strings" 10 11 "github.com/mattermost/mattermost-server/v5/model" 12 "github.com/spf13/cobra" 13 ) 14 15 var IntegrityCmd = &cobra.Command{ 16 Use: "integrity", 17 Short: "Check database data integrity", 18 RunE: integrityCmdF, 19 } 20 21 func init() { 22 IntegrityCmd.Flags().Bool("confirm", false, "Confirm you really want to run a complete integrity check that may temporarily harm system performance") 23 IntegrityCmd.Flags().BoolP("verbose", "v", false, "Show detailed information on integrity check results") 24 RootCmd.AddCommand(IntegrityCmd) 25 } 26 27 func printRelationalIntegrityCheckResult(data model.RelationalIntegrityCheckData, verbose bool) { 28 fmt.Printf("Found %d records in relation %s orphans of relation %s\n", 29 len(data.Records), data.ChildName, data.ParentName) 30 if !verbose { 31 return 32 } 33 for _, record := range data.Records { 34 var parentId string 35 36 if record.ParentId == nil { 37 parentId = "NULL" 38 } else if *record.ParentId == "" { 39 parentId = "empty" 40 } else { 41 parentId = *record.ParentId 42 } 43 44 if record.ChildId != nil { 45 if parentId == "NULL" || parentId == "empty" { 46 fmt.Printf(" Child %s (%s.%s) has %s ParentIdAttr (%s.%s)\n", *record.ChildId, data.ChildName, data.ChildIdAttr, parentId, data.ChildName, data.ParentIdAttr) 47 } else { 48 fmt.Printf(" Child %s (%s.%s) is missing Parent %s (%s.%s)\n", *record.ChildId, data.ChildName, data.ChildIdAttr, parentId, data.ChildName, data.ParentIdAttr) 49 } 50 } else { 51 if parentId == "NULL" || parentId == "empty" { 52 fmt.Printf(" Child has %s ParentIdAttr (%s.%s)\n", parentId, data.ChildName, data.ParentIdAttr) 53 } else { 54 fmt.Printf(" Child is missing Parent %s (%s.%s)\n", parentId, data.ChildName, data.ParentIdAttr) 55 } 56 } 57 } 58 } 59 60 func printIntegrityCheckResult(result model.IntegrityCheckResult, verbose bool) { 61 switch data := result.Data.(type) { 62 case model.RelationalIntegrityCheckData: 63 printRelationalIntegrityCheckResult(data, verbose) 64 } 65 } 66 67 func integrityCmdF(command *cobra.Command, args []string) error { 68 a, err := InitDBCommandContextCobra(command) 69 if err != nil { 70 return err 71 } 72 defer a.Srv().Shutdown() 73 74 confirmFlag, _ := command.Flags().GetBool("confirm") 75 if !confirmFlag { 76 var confirm string 77 fmt.Fprintf(os.Stdout, "This check may harm performance on live systems. Are you sure you want to proceed? (y/N): ") 78 fmt.Scanln(&confirm) 79 if !strings.EqualFold(confirm, "y") && !strings.EqualFold(confirm, "yes") { 80 fmt.Fprintf(os.Stderr, "Aborted.\n") 81 return nil 82 } 83 } 84 85 verboseFlag, _ := command.Flags().GetBool("verbose") 86 results := a.Srv().Store.CheckIntegrity() 87 for result := range results { 88 if result.Err != nil { 89 fmt.Fprintf(os.Stderr, "%s\n", result.Err.Error()) 90 break 91 } 92 printIntegrityCheckResult(result, verboseFlag) 93 } 94 95 return nil 96 }