add graph connector to backupOp (#165)

Adds graph connector to the backup operation implementation.
This includes feeding the account credentials into the
backup as well.
This commit is contained in:
Keepers 2022-06-08 17:32:14 -06:00 committed by GitHub
parent 9043351716
commit 2104e66fea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 89 additions and 21 deletions

View File

@ -13,6 +13,7 @@ permissions:
jobs: jobs:
Run-All: Run-All:
environment: Testing
runs-on: ubuntu-latest runs-on: ubuntu-latest
defaults: defaults:
run: run:
@ -50,4 +51,7 @@ jobs:
env: env:
CORSO_CI_TESTS: true CORSO_CI_TESTS: true
CORSO_PASSWORD: ${{ secrets.INTEGRATION_TEST_CORSO_PASSWORD }} CORSO_PASSWORD: ${{ secrets.INTEGRATION_TEST_CORSO_PASSWORD }}
CLIENT_ID: ${{ secrets.CLIENT_ID }}
CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }}
TENANT_ID: ${{ secrets.TENANT_ID }}
run: go test ./... run: go test ./...

View File

@ -7,6 +7,7 @@ replace github.com/kopia/kopia => github.com/alcionai/kopia v0.10.8-0.2022060816
require ( require (
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/hashicorp/go-multierror v1.1.1
github.com/kopia/kopia v0.10.7 github.com/kopia/kopia v0.10.7
github.com/microsoft/kiota-authentication-azure-go v0.3.0 github.com/microsoft/kiota-authentication-azure-go v0.3.0
github.com/microsoft/kiota-serialization-json-go v0.5.1 github.com/microsoft/kiota-serialization-json-go v0.5.1
@ -48,7 +49,6 @@ require (
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect

View File

@ -3,13 +3,20 @@ package operations
import ( import (
"context" "context"
"github.com/pkg/errors"
"github.com/alcionai/corso/internal/connector"
"github.com/alcionai/corso/internal/kopia" "github.com/alcionai/corso/internal/kopia"
"github.com/alcionai/corso/pkg/credentials"
) )
// BackupOperation wraps an operation with backup-specific props. // BackupOperation wraps an operation with backup-specific props.
type BackupOperation struct { type BackupOperation struct {
operation operation
Version string Version string
creds credentials.M365
Targets []string // something for targets/filter/source/app&users/etc Targets []string // something for targets/filter/source/app&users/etc
Work []string // something to reference the artifacts created, or at least their count Work []string // something to reference the artifacts created, or at least their count
@ -22,14 +29,13 @@ func NewBackupOperation(
ctx context.Context, ctx context.Context,
opts OperationOpts, opts OperationOpts,
kw *kopia.KopiaWrapper, kw *kopia.KopiaWrapper,
creds credentials.M365,
targets []string, targets []string,
) (BackupOperation, error) { ) (BackupOperation, error) {
// todo - initialize a graphConnector
// gc, err := graphConnector.Connect(bo.account)
bo := BackupOperation{ bo := BackupOperation{
operation: newOperation(opts, kw), operation: newOperation(opts, kw),
Version: "v0", Version: "v0",
creds: creds,
Targets: targets, Targets: targets,
Work: []string{}, Work: []string{},
} }
@ -41,11 +47,19 @@ func NewBackupOperation(
} }
func (bo BackupOperation) validate() error { func (bo BackupOperation) validate() error {
if err := bo.creds.Validate(); err != nil {
return errors.Wrap(err, "invalid credentials")
}
return bo.operation.validate() return bo.operation.validate()
} }
// Run begins a synchronous backup operation. // Run begins a synchronous backup operation.
func (bo BackupOperation) Run(ctx context.Context) error { func (bo BackupOperation) Run(ctx context.Context) error {
_, err := connector.NewGraphConnector(bo.creds.TenantID, bo.creds.ClientID, bo.creds.ClientSecret)
if err != nil {
return errors.Wrap(err, "connecting to graph api")
}
// todo - use the graphConnector to create datastreams // todo - use the graphConnector to create datastreams
// dStreams, err := bo.gc.BackupOp(bo.Targets) // dStreams, err := bo.gc.BackupOp(bo.Targets)

View File

@ -10,6 +10,7 @@ import (
"github.com/alcionai/corso/internal/kopia" "github.com/alcionai/corso/internal/kopia"
"github.com/alcionai/corso/internal/operations" "github.com/alcionai/corso/internal/operations"
ctesting "github.com/alcionai/corso/internal/testing" ctesting "github.com/alcionai/corso/internal/testing"
"github.com/alcionai/corso/pkg/credentials"
) )
type BackupOpIntegrationSuite struct { type BackupOpIntegrationSuite struct {
@ -23,24 +24,40 @@ func TestBackupOpIntegrationSuite(t *testing.T) {
suite.Run(t, new(BackupOpIntegrationSuite)) suite.Run(t, new(BackupOpIntegrationSuite))
} }
func (suite *BackupOpIntegrationSuite) SetupSuite() {
if _, err := ctesting.GetRequiredEnvVars(
credentials.TenantID,
credentials.ClientID,
credentials.ClientSecret,
); err != nil {
suite.T().Fatal(err)
}
}
func (suite *BackupOpIntegrationSuite) TestNewBackupOperation() { func (suite *BackupOpIntegrationSuite) TestNewBackupOperation() {
kw := &kopia.KopiaWrapper{}
creds := credentials.GetM365()
table := []struct { table := []struct {
name string name string
opts operations.OperationOpts opts operations.OperationOpts
kw *kopia.KopiaWrapper kw *kopia.KopiaWrapper
targets []string creds credentials.M365
targets []string
errCheck assert.ErrorAssertionFunc
}{ }{
{"good", operations.OperationOpts{}, new(kopia.KopiaWrapper), nil}, {"good", operations.OperationOpts{}, kw, creds, nil, assert.NoError},
{"missing kopia", operations.OperationOpts{}, nil, nil}, {"missing kopia", operations.OperationOpts{}, nil, creds, nil, assert.Error},
{"invalid creds", operations.OperationOpts{}, kw, credentials.M365{}, nil, assert.Error},
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
_, err := operations.NewBackupOperation( _, err := operations.NewBackupOperation(
context.Background(), context.Background(),
operations.OperationOpts{}, operations.OperationOpts{},
new(kopia.KopiaWrapper), test.kw,
test.creds,
nil) nil)
assert.NoError(t, err) test.errCheck(t, err)
}) })
} }
} }

View File

@ -2,11 +2,12 @@ package operations
import ( import (
"context" "context"
"errors"
"time" "time"
"github.com/alcionai/corso/internal/kopia"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/pkg/errors"
"github.com/alcionai/corso/internal/kopia"
) )
type opStatus int type opStatus int
@ -28,9 +29,6 @@ type operation struct {
options OperationOpts options OperationOpts
kopia *kopia.KopiaWrapper kopia *kopia.KopiaWrapper
// TODO(rkeepers) deal with circular dependencies here
// graphConn GraphConnector // m365 details
Status opStatus Status opStatus
Errors []error Errors []error
} }
@ -47,7 +45,10 @@ type OperationOpts struct {
Logger logger Logger logger
} }
func newOperation(opts OperationOpts, kw *kopia.KopiaWrapper) operation { func newOperation(
opts OperationOpts,
kw *kopia.KopiaWrapper,
) operation {
return operation{ return operation{
ID: uuid.New(), ID: uuid.New(),
CreatedAt: time.Now(), CreatedAt: time.Now(),

View File

@ -3,9 +3,10 @@ package operations
import ( import (
"testing" "testing"
"github.com/alcionai/corso/internal/kopia"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/alcionai/corso/internal/kopia"
) )
type OperationSuite struct { type OperationSuite struct {
@ -24,12 +25,13 @@ func (suite *OperationSuite) TestNewOperation() {
} }
func (suite *OperationSuite) TestOperation_Validate() { func (suite *OperationSuite) TestOperation_Validate() {
kwStub := &kopia.KopiaWrapper{}
table := []struct { table := []struct {
name string name string
kw *kopia.KopiaWrapper kw *kopia.KopiaWrapper
errCheck assert.ErrorAssertionFunc errCheck assert.ErrorAssertionFunc
}{ }{
{"good", new(kopia.KopiaWrapper), assert.NoError}, {"good", kwStub, assert.NoError},
{"missing kopia", nil, assert.Error}, {"missing kopia", nil, assert.Error},
} }
for _, test := range table { for _, test := range table {

View File

@ -0,0 +1,5 @@
package credentials
import "errors"
var errMissingRequired = errors.New("missing required storage configuration")

View File

@ -1,6 +1,10 @@
package credentials package credentials
import "os" import (
"os"
"github.com/pkg/errors"
)
// envvar consts // envvar consts
const ( const (
@ -26,3 +30,17 @@ func GetM365() M365 {
TenantID: os.Getenv(TenantID), TenantID: os.Getenv(TenantID),
} }
} }
func (c M365) Validate() error {
check := map[string]string{
ClientID: c.ClientID,
ClientSecret: c.ClientSecret,
TenantID: c.TenantID,
}
for k, v := range check {
if len(v) == 0 {
return errors.Wrap(errMissingRequired, k)
}
}
return nil
}

View File

@ -9,6 +9,7 @@ import (
"github.com/alcionai/corso/internal/kopia" "github.com/alcionai/corso/internal/kopia"
"github.com/alcionai/corso/internal/operations" "github.com/alcionai/corso/internal/operations"
"github.com/alcionai/corso/pkg/credentials"
"github.com/alcionai/corso/pkg/storage" "github.com/alcionai/corso/pkg/storage"
) )
@ -106,9 +107,15 @@ func (r *Repository) Close(ctx context.Context) error {
// NewBackup generates a backupOperation runner. // NewBackup generates a backupOperation runner.
func (r Repository) NewBackup(ctx context.Context, targets []string) (operations.BackupOperation, error) { func (r Repository) NewBackup(ctx context.Context, targets []string) (operations.BackupOperation, error) {
creds := credentials.M365{
ClientID: r.Account.ClientID,
ClientSecret: r.Account.ClientSecret,
TenantID: r.Account.TenantID,
}
return operations.NewBackupOperation( return operations.NewBackupOperation(
ctx, ctx,
operations.OperationOpts{}, operations.OperationOpts{},
r.dataLayer, r.dataLayer,
creds,
targets) targets)
} }