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:
parent
313bbe7601
commit
39b47cc123
178
src/cmd/getM365/getItem.go
Normal file
178
src/cmd/getM365/getItem.go
Normal 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
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user