Gc mock package (#1313)

## Description
Command line utility that allows for the printing of mockData based on the m365ID. Supports:
- `exchange.Mail` 
- `exchange.Contacts`
- `exchange.Events`

<!-- Insert PR description-->

## Type of change

- [x] 🌻 Feature

## Issue(s)

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

Related to:
* #1255<issue>
* #999 
* #705
This commit is contained in:
Danny 2022-10-25 14:50:39 -04:00 committed by GitHub
parent 313bbe7601
commit 39b47cc123
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 199 additions and 3 deletions

178
src/cmd/getM365/getItem.go Normal file
View File

@ -0,0 +1,178 @@
// getItem.go is a source file designed to retrieve an m365 object from an
// existing M365 account. Data displayed is representative of the current
// serialization abstraction versioning used by Microsoft Graph and stored by Corso.
package main
import (
"bytes"
"context"
"fmt"
"os"
kw "github.com/microsoft/kiota-serialization-json-go"
"github.com/pkg/errors"
"github.com/spf13/cobra"
. "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/connector"
"github.com/alcionai/corso/src/internal/connector/exchange"
"github.com/alcionai/corso/src/internal/connector/graph"
"github.com/alcionai/corso/src/internal/connector/support"
"github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/pkg/account"
"github.com/alcionai/corso/src/pkg/credentials"
"github.com/alcionai/corso/src/pkg/logger"
"github.com/alcionai/corso/src/pkg/path"
)
var getCmd = &cobra.Command{
Use: "get",
Short: "Get a M365ID item JSON",
RunE: handleGetCommand,
}
// Required inputs from user for command execution
var (
tenant, user, m365ID, category string
)
// main function will produce the JSON String for a given m365 object of a
// user. Displayed Objects can be used as inputs for Mockable data
// Supports:
// - exchange (contacts, email, and events)
// Input: go run ./getItem.go --user <user>
// --m365ID <m365ID> --category <oneof: contacts, email, events>
func main() {
ctx, _ := logger.SeedLevel(context.Background(), logger.Development)
ctx = SetRootCmd(ctx, getCmd)
defer logger.Flush(ctx)
fs := getCmd.PersistentFlags()
fs.StringVar(&user, "user", "", "m365 user id of M365 user")
fs.StringVar(&tenant, "tenant", "",
"m365 Tenant: m365 identifier for the tenant, not required if active in OS Environment")
fs.StringVar(&m365ID, "m365ID", "", "m365 identifier for object to be created")
fs.StringVar(&category, "category", "", "type of M365 data (contacts, email, events or files)") // files not supported
cobra.CheckErr(getCmd.MarkPersistentFlagRequired("user"))
cobra.CheckErr(getCmd.MarkPersistentFlagRequired("m365ID"))
cobra.CheckErr(getCmd.MarkPersistentFlagRequired("category"))
if err := getCmd.ExecuteContext(ctx); err != nil {
os.Exit(1)
}
}
func handleGetCommand(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
if utils.HasNoFlagsAndShownHelp(cmd) {
return nil
}
gc, err := getGC(ctx)
if err != nil {
return err
}
err = runDisplayM365JSON(
ctx,
gc)
if err != nil {
return Only(ctx, errors.Wrapf(err, "unable to create mock from M365: %s", m365ID))
}
return nil
}
func runDisplayM365JSON(
ctx context.Context,
gs graph.Service,
) error {
var (
get exchange.GraphRetrievalFunc
serializeFunc exchange.GraphSerializeFunc
cat = graph.StringToPathCategory(category)
)
switch cat {
case path.EmailCategory, path.EventsCategory, path.ContactsCategory:
get, serializeFunc = exchange.GetQueryAndSerializeFunc(exchange.CategoryToOptionIdentifier(cat))
default:
return fmt.Errorf("unable to process category: %s", cat)
}
channel := make(chan data.Stream, 1)
sw := kw.NewJsonSerializationWriter()
response, err := get(ctx, gs, user, m365ID)
if err != nil {
return errors.Wrap(err, support.ConnectorStackErrorTrace(err))
}
// First return is the number of bytes that were serialized. Ignored
_, err = serializeFunc(ctx, gs.Client(), sw, channel, response, user)
close(channel)
if err != nil {
return err
}
for item := range channel {
buf := &bytes.Buffer{}
_, err := buf.ReadFrom(item.ToReader())
if err != nil {
return errors.Wrapf(err, "unable to parse given data: %s", m365ID)
}
byteArray := buf.Bytes()
newValue := string(byteArray)
err = sw.WriteStringValue("", &newValue)
if err != nil {
return errors.Wrapf(err, "unable to %s to string value", m365ID)
}
array, err := sw.GetSerializedContent()
if err != nil {
return errors.Wrapf(err, "unable to serialize new value from M365:%s", m365ID)
}
fmt.Println(string(array))
return nil
}
// This should never happen
return errors.New("m365 object not serialized")
}
//-------------------------------------------------------------------------------
// Helpers
//-------------------------------------------------------------------------------
func getGC(ctx context.Context) (*connector.GraphConnector, error) {
// get account info
m365Cfg := account.M365Config{
M365: credentials.GetM365(),
AzureTenantID: common.First(tenant, os.Getenv(account.AzureTenantID)),
}
acct, err := account.NewAccount(account.ProviderM365, m365Cfg)
if err != nil {
return nil, Only(ctx, errors.Wrap(err, "finding m365 account details"))
}
gc, err := connector.NewGraphConnector(ctx, acct)
if err != nil {
return nil, Only(ctx, errors.Wrap(err, "connecting to graph API"))
}
return gc, nil
}

View File

@ -105,7 +105,7 @@ const (
contacts contacts
) )
func categoryToOptionIdentifier(category path.CategoryType) optionIdentifier { func CategoryToOptionIdentifier(category path.CategoryType) optionIdentifier {
switch category { switch category {
case path.EmailCategory: case path.EmailCategory:
return messages return messages

View File

@ -29,7 +29,7 @@ func FilterContainersAndFillCollections(
) error { ) error {
var ( var (
category = graph.ScopeToPathCategory(qp.Scope) category = graph.ScopeToPathCategory(qp.Scope)
collectionType = categoryToOptionIdentifier(category) collectionType = CategoryToOptionIdentifier(category)
errs error errs error
) )

View File

@ -36,7 +36,7 @@ func RestoreExchangeObject(
return nil, fmt.Errorf("restore policy: %s not supported for RestoreExchangeObject", policy) return nil, fmt.Errorf("restore policy: %s not supported for RestoreExchangeObject", policy)
} }
setting := categoryToOptionIdentifier(category) setting := CategoryToOptionIdentifier(category)
switch setting { switch setting {
case messages: case messages:

View File

@ -5,6 +5,7 @@ import (
nethttp "net/http" nethttp "net/http"
"net/http/httputil" "net/http/httputil"
"os" "os"
"strings"
"time" "time"
az "github.com/Azure/azure-sdk-for-go/sdk/azidentity" az "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
@ -85,3 +86,20 @@ func ScopeToPathCategory(scope selectors.ExchangeScope) path.CategoryType {
return path.UnknownCategory return path.UnknownCategory
} }
func StringToPathCategory(input string) path.CategoryType {
param := strings.ToLower(input)
switch param {
case "email":
return path.EmailCategory
case "contacts":
return path.ContactsCategory
case "events":
return path.EventsCategory
case "files":
return path.FilesCategory
default:
return path.UnknownCategory
}
}