Fix compile error in factory script (#2092)

## Description

Go does not allow importing code from a file marked as package main into another file.

## Does this PR need a docs update or release note?

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No 

## Type of change

- [ ] 🌻 Feature
- [x] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [x] 🧹 Tech Debt/Cleanup

## Issue(s)

* closes #2026 

## Test Plan

- [x] 💪 Manual
- [ ]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2023-01-10 17:04:41 -08:00 committed by GitHub
parent 580934b069
commit 6967f1bf6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 226 additions and 216 deletions

View File

@ -3,25 +3,12 @@ package main
import (
"context"
"os"
"strings"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/spf13/cobra"
. "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/connector"
"github.com/alcionai/corso/src/internal/connector/mockconnector"
"github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/pkg/account"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/credentials"
"github.com/alcionai/corso/src/cmd/factory/impl"
"github.com/alcionai/corso/src/pkg/logger"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/selectors"
)
var factoryCmd = &cobra.Command{
@ -42,17 +29,6 @@ var oneDriveCmd = &cobra.Command{
RunE: handleOneDriveFactory,
}
var (
count int
destination string
tenant string
user string
)
// TODO: ErrGenerating = errors.New("not all items were successfully generated")
var ErrNotYetImplemeted = errors.New("not yet implemented")
// ------------------------------------------------------------------------------------------
// CLI command handlers
// ------------------------------------------------------------------------------------------
@ -65,18 +41,18 @@ func main() {
// persistent flags that are common to all use cases
fs := factoryCmd.PersistentFlags()
fs.StringVar(&tenant, "tenant", "", "m365 tenant containing the user")
fs.StringVar(&user, "user", "", "m365 user owning the new data")
fs.StringVar(&impl.Tenant, "tenant", "", "m365 tenant containing the user")
fs.StringVar(&impl.User, "user", "", "m365 user owning the new data")
cobra.CheckErr(factoryCmd.MarkPersistentFlagRequired("user"))
fs.IntVar(&count, "count", 0, "count of items to produce")
fs.IntVar(&impl.Count, "count", 0, "count of items to produce")
cobra.CheckErr(factoryCmd.MarkPersistentFlagRequired("count"))
fs.StringVar(&destination, "destination", "", "destination of the new data (will create as needed)")
fs.StringVar(&impl.Destination, "destination", "", "destination of the new data (will create as needed)")
cobra.CheckErr(factoryCmd.MarkPersistentFlagRequired("destination"))
factoryCmd.AddCommand(exchangeCmd)
addExchangeCommands(exchangeCmd)
impl.AddExchangeCommands(exchangeCmd)
factoryCmd.AddCommand(oneDriveCmd)
addOneDriveCommands(oneDriveCmd)
impl.AddOneDriveCommands(oneDriveCmd)
if err := factoryCmd.ExecuteContext(ctx); err != nil {
logger.Flush(ctx)
@ -85,180 +61,16 @@ func main() {
}
func handleFactoryRoot(cmd *cobra.Command, args []string) error {
Err(cmd.Context(), ErrNotYetImplemeted)
Err(cmd.Context(), impl.ErrNotYetImplemeted)
return cmd.Help()
}
func handleExchangeFactory(cmd *cobra.Command, args []string) error {
Err(cmd.Context(), ErrNotYetImplemeted)
Err(cmd.Context(), impl.ErrNotYetImplemeted)
return cmd.Help()
}
func handleOneDriveFactory(cmd *cobra.Command, args []string) error {
Err(cmd.Context(), ErrNotYetImplemeted)
Err(cmd.Context(), impl.ErrNotYetImplemeted)
return cmd.Help()
}
// ------------------------------------------------------------------------------------------
// Restoration
// ------------------------------------------------------------------------------------------
type dataBuilderFunc func(id, now, subject, body string) []byte
func generateAndRestoreItems(
ctx context.Context,
gc *connector.GraphConnector,
acct account.Account,
service path.ServiceType,
cat path.CategoryType,
sel selectors.Selector,
userID, destFldr string,
howMany int,
dbf dataBuilderFunc,
) (*details.Details, error) {
items := make([]item, 0, howMany)
for i := 0; i < howMany; i++ {
var (
now = common.Now()
nowLegacy = common.FormatLegacyTime(time.Now())
id = uuid.NewString()
subject = "automated " + now[:16] + " - " + id[:8]
body = "automated " + cat.String() + " generation for " + userID + " at " + now + " - " + id
)
items = append(items, item{
name: id,
data: dbf(id, nowLegacy, subject, body),
})
}
collections := []collection{{
pathElements: []string{destFldr},
category: cat,
items: items,
}}
// TODO: fit the desination to the containers
dest := control.DefaultRestoreDestination(common.SimpleTimeTesting)
dest.ContainerName = destFldr
dataColls, err := buildCollections(
service,
acct.ID(), userID,
dest,
collections,
)
if err != nil {
return nil, err
}
Infof(ctx, "Generating %d %s items in %s\n", howMany, cat, destination)
return gc.RestoreDataCollections(ctx, acct, sel, dest, dataColls)
}
// ------------------------------------------------------------------------------------------
// Common Helpers
// ------------------------------------------------------------------------------------------
func getGCAndVerifyUser(ctx context.Context, userID string) (*connector.GraphConnector, account.Account, error) {
tid := common.First(tenant, os.Getenv(account.AzureTenantID))
// get account info
m365Cfg := account.M365Config{
M365: credentials.GetM365(),
AzureTenantID: tid,
}
acct, err := account.NewAccount(account.ProviderM365, m365Cfg)
if err != nil {
return nil, account.Account{}, errors.Wrap(err, "finding m365 account details")
}
// build a graph connector
gc, err := connector.NewGraphConnector(ctx, acct, connector.Users)
if err != nil {
return nil, account.Account{}, errors.Wrap(err, "connecting to graph api")
}
normUsers := map[string]struct{}{}
for k := range gc.Users {
normUsers[strings.ToLower(k)] = struct{}{}
}
if _, ok := normUsers[strings.ToLower(user)]; !ok {
return nil, account.Account{}, errors.New("user not found within tenant")
}
return gc, acct, nil
}
type item struct {
name string
data []byte
}
type collection struct {
// Elements (in order) for the path representing this collection. Should
// only contain elements after the prefix that corso uses for the path. For
// example, a collection for the Inbox folder in exchange mail would just be
// "Inbox".
pathElements []string
category path.CategoryType
items []item
}
func buildCollections(
service path.ServiceType,
tenant, user string,
dest control.RestoreDestination,
colls []collection,
) ([]data.Collection, error) {
collections := make([]data.Collection, 0, len(colls))
for _, c := range colls {
pth, err := toDataLayerPath(
service,
tenant,
user,
c.category,
c.pathElements,
false,
)
if err != nil {
return nil, err
}
mc := mockconnector.NewMockExchangeCollection(pth, len(c.items))
for i := 0; i < len(c.items); i++ {
mc.Names[i] = c.items[i].name
mc.Data[i] = c.items[i].data
}
collections = append(collections, mc)
}
return collections, nil
}
func toDataLayerPath(
service path.ServiceType,
tenant, user string,
category path.CategoryType,
elements []string,
isItem bool,
) (path.Path, error) {
pb := path.Builder{}.Append(elements...)
switch service {
case path.ExchangeService:
return pb.ToDataLayerExchangePathForCategory(tenant, user, category, isItem)
case path.OneDriveService:
return pb.ToDataLayerOneDrivePath(tenant, user, isItem)
}
return nil, errors.Errorf("unknown service %s", service.String())
}

View File

@ -0,0 +1,198 @@
package impl
import (
"context"
"os"
"strings"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
. "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/connector"
"github.com/alcionai/corso/src/internal/connector/mockconnector"
"github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/pkg/account"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/credentials"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/selectors"
)
var (
Count int
Destination string
Tenant string
User string
)
// TODO: ErrGenerating = errors.New("not all items were successfully generated")
var ErrNotYetImplemeted = errors.New("not yet implemented")
// ------------------------------------------------------------------------------------------
// Restoration
// ------------------------------------------------------------------------------------------
type dataBuilderFunc func(id, now, subject, body string) []byte
func generateAndRestoreItems(
ctx context.Context,
gc *connector.GraphConnector,
acct account.Account,
service path.ServiceType,
cat path.CategoryType,
sel selectors.Selector,
tenantID, userID, destFldr string,
howMany int,
dbf dataBuilderFunc,
) (*details.Details, error) {
items := make([]item, 0, howMany)
for i := 0; i < howMany; i++ {
var (
now = common.Now()
nowLegacy = common.FormatLegacyTime(time.Now())
id = uuid.NewString()
subject = "automated " + now[:16] + " - " + id[:8]
body = "automated " + cat.String() + " generation for " + userID + " at " + now + " - " + id
)
items = append(items, item{
name: id,
data: dbf(id, nowLegacy, subject, body),
})
}
collections := []collection{{
pathElements: []string{destFldr},
category: cat,
items: items,
}}
// TODO: fit the desination to the containers
dest := control.DefaultRestoreDestination(common.SimpleTimeTesting)
dest.ContainerName = destFldr
dataColls, err := buildCollections(
service,
tenantID, userID,
dest,
collections,
)
if err != nil {
return nil, err
}
Infof(ctx, "Generating %d %s items in %s\n", howMany, cat, Destination)
return gc.RestoreDataCollections(ctx, acct, sel, dest, dataColls)
}
// ------------------------------------------------------------------------------------------
// Common Helpers
// ------------------------------------------------------------------------------------------
func getGCAndVerifyUser(ctx context.Context, userID string) (*connector.GraphConnector, account.Account, error) {
tid := common.First(Tenant, os.Getenv(account.AzureTenantID))
// get account info
m365Cfg := account.M365Config{
M365: credentials.GetM365(),
AzureTenantID: tid,
}
acct, err := account.NewAccount(account.ProviderM365, m365Cfg)
if err != nil {
return nil, account.Account{}, errors.Wrap(err, "finding m365 account details")
}
// build a graph connector
gc, err := connector.NewGraphConnector(ctx, acct, connector.Users)
if err != nil {
return nil, account.Account{}, errors.Wrap(err, "connecting to graph api")
}
normUsers := map[string]struct{}{}
for k := range gc.Users {
normUsers[strings.ToLower(k)] = struct{}{}
}
if _, ok := normUsers[strings.ToLower(User)]; !ok {
return nil, account.Account{}, errors.New("user not found within tenant")
}
return gc, acct, nil
}
type item struct {
name string
data []byte
}
type collection struct {
// Elements (in order) for the path representing this collection. Should
// only contain elements after the prefix that corso uses for the path. For
// example, a collection for the Inbox folder in exchange mail would just be
// "Inbox".
pathElements []string
category path.CategoryType
items []item
}
func buildCollections(
service path.ServiceType,
tenant, user string,
dest control.RestoreDestination,
colls []collection,
) ([]data.Collection, error) {
collections := make([]data.Collection, 0, len(colls))
for _, c := range colls {
pth, err := toDataLayerPath(
service,
tenant,
user,
c.category,
c.pathElements,
false,
)
if err != nil {
return nil, err
}
mc := mockconnector.NewMockExchangeCollection(pth, len(c.items))
for i := 0; i < len(c.items); i++ {
mc.Names[i] = c.items[i].name
mc.Data[i] = c.items[i].data
}
collections = append(collections, mc)
}
return collections, nil
}
func toDataLayerPath(
service path.ServiceType,
tenant, user string,
category path.CategoryType,
elements []string,
isItem bool,
) (path.Path, error) {
pb := path.Builder{}.Append(elements...)
switch service {
case path.ExchangeService:
return pb.ToDataLayerExchangePathForCategory(tenant, user, category, isItem)
case path.OneDriveService:
return pb.ToDataLayerOneDrivePath(tenant, user, isItem)
}
return nil, errors.Errorf("unknown service %s", service.String())
}

View File

@ -1,4 +1,4 @@
package main
package impl
import (
"github.com/spf13/cobra"
@ -30,7 +30,7 @@ var (
}
)
func addExchangeCommands(cmd *cobra.Command) {
func AddExchangeCommands(cmd *cobra.Command) {
cmd.AddCommand(emailsCmd)
cmd.AddCommand(eventsCmd)
cmd.AddCommand(contactsCmd)
@ -47,7 +47,7 @@ func handleExchangeEmailFactory(cmd *cobra.Command, args []string) error {
return nil
}
gc, acct, err := getGCAndVerifyUser(ctx, user)
gc, acct, err := getGCAndVerifyUser(ctx, User)
if err != nil {
return Only(ctx, err)
}
@ -58,12 +58,12 @@ func handleExchangeEmailFactory(cmd *cobra.Command, args []string) error {
acct,
service,
category,
selectors.NewExchangeRestore([]string{user}).Selector,
user, destination,
count,
selectors.NewExchangeRestore([]string{User}).Selector,
Tenant, User, Destination,
Count,
func(id, now, subject, body string) []byte {
return mockconnector.GetMockMessageWith(
user, user, user,
User, User, User,
subject, body, body,
now, now, now, now)
},
@ -88,7 +88,7 @@ func handleExchangeCalendarEventFactory(cmd *cobra.Command, args []string) error
return nil
}
gc, acct, err := getGCAndVerifyUser(ctx, user)
gc, acct, err := getGCAndVerifyUser(ctx, User)
if err != nil {
return Only(ctx, err)
}
@ -99,12 +99,12 @@ func handleExchangeCalendarEventFactory(cmd *cobra.Command, args []string) error
acct,
service,
category,
selectors.NewExchangeRestore([]string{user}).Selector,
user, destination,
count,
selectors.NewExchangeRestore([]string{User}).Selector,
Tenant, User, Destination,
Count,
func(id, now, subject, body string) []byte {
return mockconnector.GetMockEventWith(
user, subject, body, body,
User, subject, body, body,
now, now, false)
},
)
@ -128,7 +128,7 @@ func handleExchangeContactFactory(cmd *cobra.Command, args []string) error {
return nil
}
gc, acct, err := getGCAndVerifyUser(ctx, user)
gc, acct, err := getGCAndVerifyUser(ctx, User)
if err != nil {
return Only(ctx, err)
}
@ -139,9 +139,9 @@ func handleExchangeContactFactory(cmd *cobra.Command, args []string) error {
acct,
service,
category,
selectors.NewExchangeRestore([]string{user}).Selector,
user, destination,
count,
selectors.NewExchangeRestore([]string{User}).Selector,
Tenant, User, Destination,
Count,
func(id, now, subject, body string) []byte {
given, mid, sur := id[:8], id[9:13], id[len(id)-12:]

View File

@ -1,4 +1,4 @@
package main
package impl
import (
"github.com/spf13/cobra"
@ -13,7 +13,7 @@ var filesCmd = &cobra.Command{
RunE: handleOneDriveFileFactory,
}
func addOneDriveCommands(cmd *cobra.Command) {
func AddOneDriveCommands(cmd *cobra.Command) {
cmd.AddCommand(filesCmd)
}