## Description Github workflow - Release sanity test which can run pre and post release. Testing- - version command - repo init and connect - backup and restore of exchange and onedrive - verify correct no. of emails restored - verify file sizes restored and roles on folder are correct. - incremental backup and verification of the same **Further enhancement-** - check actual email data instead of just no. of emails - verify contacts and calendar - permission in onedrive - slack notification on failure - if we recieve an email in between a backup and restore, we will fail the test as the counts won't match **issues for handling enhancement-** https://github.com/alcionai/corso/issues/2743 https://github.com/alcionai/corso/issues/2742 ## Does this PR need a docs update or release note? - [ ] ⛔ No ## Type of change <!--- Please check the type of change your PR introduces: ---> - [x] 🤖 Test ## Issue(s) <!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. --> * https://github.com/alcionai/corso/pull/2622/ ## Test Plan - [ ] 💪 Manual
232 lines
5.9 KiB
Go
232 lines
5.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
|
"github.com/alcionai/corso/src/internal/connector/graph"
|
|
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
|
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
|
"github.com/microsoftgraph/msgraph-sdk-go/users"
|
|
)
|
|
|
|
func main() {
|
|
adapter, err := graph.CreateAdapter(
|
|
os.Getenv("AZURE_TENANT_ID"),
|
|
os.Getenv("AZURE_CLIENT_ID"),
|
|
os.Getenv("AZURE_CLIENT_SECRET"),
|
|
)
|
|
if err != nil {
|
|
fmt.Println("error while creating adapter: ", err)
|
|
os.Exit(1)
|
|
|
|
return
|
|
}
|
|
|
|
testUser := os.Getenv("CORSO_M365_TEST_USER_ID")
|
|
folder := strings.TrimSpace(os.Getenv("RESTORE_FOLDER"))
|
|
|
|
restoreStartTime := strings.SplitAfter(folder, "Corso_Restore_")[1]
|
|
startTime, _ := time.Parse(time.RFC822, restoreStartTime)
|
|
|
|
fmt.Println("Restore folder: ", folder)
|
|
|
|
client := msgraphsdk.NewGraphServiceClient(adapter)
|
|
|
|
switch service := os.Getenv("RESTORE_SERVICE"); service {
|
|
case "exchange":
|
|
checkEmailRestoration(client, testUser, folder, startTime)
|
|
default:
|
|
checkOnedriveRestoration(client, testUser, folder, startTime)
|
|
}
|
|
}
|
|
|
|
func checkEmailRestoration(client *msgraphsdk.GraphServiceClient, testUser, folderName string, startTime time.Time) {
|
|
var (
|
|
messageCount = make(map[string]int32)
|
|
restoreFolder models.MailFolderable
|
|
)
|
|
|
|
builder := client.UsersById(testUser).MailFolders()
|
|
|
|
for {
|
|
result, err := builder.Get(context.Background(), nil)
|
|
if err != nil {
|
|
fmt.Printf("Error getting the drive: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
res := result.GetValue()
|
|
|
|
for _, r := range res {
|
|
name := *r.GetDisplayName()
|
|
|
|
var rStartTime time.Time
|
|
|
|
restoreStartTime := strings.SplitAfter(name, "Corso_Restore_")
|
|
if len(restoreStartTime) > 1 {
|
|
rStartTime, _ = time.Parse(time.RFC822, restoreStartTime[1])
|
|
if startTime.Before(rStartTime) {
|
|
fmt.Printf("The restore folder %s was created after %s. Will skip check.", name, folderName)
|
|
continue
|
|
}
|
|
}
|
|
|
|
if name == folderName {
|
|
restoreFolder = r
|
|
continue
|
|
}
|
|
|
|
messageCount[*r.GetDisplayName()] = *r.GetTotalItemCount()
|
|
}
|
|
|
|
link, ok := ptr.ValOK(result.GetOdataNextLink())
|
|
if !ok {
|
|
break
|
|
}
|
|
|
|
builder = users.NewItemMailFoldersRequestBuilder(link, client.GetAdapter())
|
|
}
|
|
|
|
user := client.UsersById(testUser)
|
|
folder := user.MailFoldersById(*restoreFolder.GetId())
|
|
|
|
childFolder, err := folder.ChildFolders().Get(context.Background(), nil)
|
|
if err != nil {
|
|
fmt.Printf("Error getting the drive: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
for _, restore := range childFolder.GetValue() {
|
|
if messageCount[*restore.GetDisplayName()] != *restore.GetTotalItemCount() {
|
|
fmt.Println("Restore was not succesfull for: ",
|
|
*restore.GetDisplayName(),
|
|
"Folder count: ",
|
|
messageCount[*restore.GetDisplayName()],
|
|
"Restore count: ",
|
|
*restore.GetTotalItemCount())
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
func checkOnedriveRestoration(client *msgraphsdk.GraphServiceClient, testUser, folderName string, startTime time.Time) {
|
|
file := make(map[string]int64)
|
|
folderPermission := make(map[string][]string)
|
|
restoreFolderID := ""
|
|
|
|
drive, err := client.UsersById(testUser).Drive().Get(context.Background(), nil)
|
|
if err != nil {
|
|
fmt.Printf("Error getting the drive: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
response, err := client.DrivesById(*drive.GetId()).Root().Children().Get(context.Background(), nil)
|
|
if err != nil {
|
|
fmt.Printf("Error getting drive by id: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
for _, driveItem := range response.GetValue() {
|
|
if *driveItem.GetName() == folderName {
|
|
restoreFolderID = *driveItem.GetId()
|
|
continue
|
|
}
|
|
|
|
var rStartTime time.Time
|
|
|
|
restoreStartTime := strings.SplitAfter(*driveItem.GetName(), "Corso_Restore_")
|
|
if len(restoreStartTime) > 1 {
|
|
rStartTime, _ = time.Parse(time.RFC822, restoreStartTime[1])
|
|
if startTime.Before(rStartTime) {
|
|
fmt.Printf("The restore folder %s was created after %s. Will skip check.", *driveItem.GetName(), folderName)
|
|
continue
|
|
}
|
|
}
|
|
|
|
// if it's a file check the size
|
|
if driveItem.GetFile() != nil {
|
|
file[*driveItem.GetName()] = *driveItem.GetSize()
|
|
}
|
|
|
|
if driveItem.GetFolder() != nil {
|
|
permission, err := client.
|
|
DrivesById(*drive.GetId()).
|
|
ItemsById(*driveItem.GetId()).
|
|
Permissions().
|
|
Get(context.TODO(), nil)
|
|
if err != nil {
|
|
fmt.Printf("Error getting item by id: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// check if permission are correct on folder
|
|
for _, permission := range permission.GetValue() {
|
|
folderPermission[*driveItem.GetName()] = permission.GetRoles()
|
|
}
|
|
|
|
continue
|
|
}
|
|
}
|
|
|
|
checkFileData(client, *drive.GetId(), restoreFolderID, file, folderPermission)
|
|
|
|
fmt.Println("Success")
|
|
}
|
|
|
|
func checkFileData(
|
|
client *msgraphsdk.GraphServiceClient,
|
|
driveID,
|
|
restoreFolderID string,
|
|
file map[string]int64,
|
|
folderPermission map[string][]string,
|
|
) {
|
|
itemBuilder := client.DrivesById(driveID).ItemsById(restoreFolderID)
|
|
|
|
restoreResponses, err := itemBuilder.Children().Get(context.Background(), nil)
|
|
if err != nil {
|
|
fmt.Printf("Error getting child folder: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
for _, restoreData := range restoreResponses.GetValue() {
|
|
restoreName := *restoreData.GetName()
|
|
|
|
if restoreData.GetFile() != nil {
|
|
if *restoreData.GetSize() != file[restoreName] {
|
|
fmt.Printf("Size of file %s is different in drive %d and restored file: %d ",
|
|
restoreName,
|
|
file[restoreName],
|
|
*restoreData.GetSize())
|
|
os.Exit(1)
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
itemBuilder := client.DrivesById(driveID).ItemsById(*restoreData.GetId())
|
|
|
|
permissionColl, err := itemBuilder.Permissions().Get(context.TODO(), nil)
|
|
if err != nil {
|
|
fmt.Printf("Error getting permission: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
userPermission := []string{}
|
|
|
|
for _, perm := range permissionColl.GetValue() {
|
|
userPermission = perm.GetRoles()
|
|
}
|
|
|
|
if !reflect.DeepEqual(folderPermission[restoreName], userPermission) {
|
|
fmt.Printf("Permission mismatch for %s.", restoreName)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
}
|