diff --git a/ocis-pkg/roles/manager.go b/ocis-pkg/roles/manager.go index 1878db020..6c58239ed 100644 --- a/ocis-pkg/roles/manager.go +++ b/ocis-pkg/roles/manager.go @@ -46,6 +46,7 @@ func (m *Manager) List(ctx context.Context, roleIDs []string) []*settingsmsg.Bun res, err := m.roleService.ListRoles(ctx, request) if err != nil { m.logger.Debug().Err(err).Msg("failed to fetch roles by roleIDs") + return nil } for _, role := range res.Bundles { m.cache.set(role.Id, role) diff --git a/settings/pkg/service/v0/service.go b/settings/pkg/service/v0/service.go index 5c372954b..87dc662e2 100644 --- a/settings/pkg/service/v0/service.go +++ b/settings/pkg/service/v0/service.go @@ -88,6 +88,11 @@ func (g Service) CheckPermission(ctx context.Context, req *permissions.CheckPerm // RegisterDefaultRoles composes default roles and saves them. Skipped if the roles already exist. func (g Service) RegisterDefaultRoles() { + // TODO: we can't register on service start any more because metadata might not be up yet + // we need to lazy initialize + if true { + return + } // FIXME: we're writing default roles per service start (i.e. twice at the moment, for http and grpc server). has to happen only once. for _, role := range generateBundlesDefaultRoles() { bundleID := role.Extension + "." + role.Id diff --git a/settings/pkg/store/metadata/assignments.go b/settings/pkg/store/metadata/assignments.go index 9c2dcbb1e..6c311b8b2 100644 --- a/settings/pkg/store/metadata/assignments.go +++ b/settings/pkg/store/metadata/assignments.go @@ -11,6 +11,7 @@ import ( // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { + s.Init() assIDs, err := s.mdc.ReadDir(nil, accountPath(accountUUID)) if err != nil { return nil, err @@ -36,6 +37,7 @@ func (s Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleA // WriteRoleAssignment appends the given role assignment to the existing assignments of the respective account. func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.UserRoleAssignment, error) { + s.Init() // as per https://github.com/owncloud/product/issues/103 "Each user can have exactly one role" err := s.mdc.Delete(nil, accountPath(accountUUID)) if err != nil { @@ -61,6 +63,7 @@ func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*settingsmsg.Use // RemoveRoleAssignment deletes the given role assignment from the existing assignments of the respective account. func (s Store) RemoveRoleAssignment(assignmentID string) error { + s.Init() accounts, err := s.mdc.ReadDir(nil, accountsFolderLocation) if err != nil { return err diff --git a/settings/pkg/store/metadata/bundles.go b/settings/pkg/store/metadata/bundles.go index 16e700d24..3dca510b0 100644 --- a/settings/pkg/store/metadata/bundles.go +++ b/settings/pkg/store/metadata/bundles.go @@ -11,6 +11,7 @@ import ( // ListBundles returns all bundles in the dataPath folder that match the given type. func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) { + s.Init() var bundles []*settingsmsg.Bundle for _, id := range bundleIDs { b, err := s.mdc.SimpleDownload(nil, bundlePath(id)) @@ -34,6 +35,7 @@ func (s Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []strin // ReadBundle tries to find a bundle by the given id within the dataPath. func (s Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) { + s.Init() b, err := s.mdc.SimpleDownload(nil, bundlePath(bundleID)) if err != nil { return nil, err @@ -50,6 +52,7 @@ func (s Store) ReadSetting(settingID string) (*settingsmsg.Setting, error) { // WriteBundle sends the givens record to the metadataclient. returns `record` for legacy reasons func (s Store) WriteBundle(record *settingsmsg.Bundle) (*settingsmsg.Bundle, error) { + s.Init() b, err := json.Marshal(record) if err != nil { return nil, err diff --git a/settings/pkg/store/metadata/store.go b/settings/pkg/store/metadata/store.go index 629439287..791ffbe29 100644 --- a/settings/pkg/store/metadata/store.go +++ b/settings/pkg/store/metadata/store.go @@ -3,8 +3,8 @@ package store import ( "context" - "fmt" "log" + "sync" "github.com/cs3org/reva/pkg/storage/utils/metadata" olog "github.com/owncloud/ocis/ocis-pkg/log" @@ -30,6 +30,7 @@ type MetadataClient interface { Delete(ctx context.Context, id string) error ReadDir(ctx context.Context, id string) ([]string, error) MakeDirIfNotExist(ctx context.Context, id string) error + Init(ctx context.Context, id string) error } // Store interacts with the filesystem to manage settings information @@ -37,6 +38,34 @@ type Store struct { Logger olog.Logger mdc MetadataClient + cfg *config.Config + + init *sync.Once + l *sync.Mutex +} + +// Init initialize the store once, later calls are noops +func (s Store) Init() { + if s.mdc != nil { + return + } + + s.l.Lock() + defer s.l.Unlock() + var err error + s.init.Do(func() { + //b := backoff.NewExponentialBackOff() + //b.MaxElapsedTime = 4 * time.Second + //backoff.Retry(func() error { + err = s.initMetadataClient() + //return err + + //}, b) + + }) + if err != nil { + log.Fatal(err) + } } // New creates a new store @@ -48,9 +77,10 @@ func New(cfg *config.Config) settings.Manager { //olog.Level(cfg.Log.Level), //olog.File(cfg.Log.File), //), + l: &sync.Mutex{}, + init: &sync.Once{}, } - s.mdc = NewMetadataClient(cfg) return &s } @@ -60,11 +90,17 @@ func NewMetadataClient(cfg *config.Config) MetadataClient { if err != nil { log.Fatal("error connecting to mdc:", err) } + return mdc - fmt.Println(settingsSpaceID) - err = mdc.Init(nil, settingsSpaceID) +} + +// we need to lazy initialize the MetadataClient because metadata service might not be ready +func (s Store) initMetadataClient() error { + s.mdc = NewMetadataClient(s.cfg) + + err := s.mdc.Init(nil, settingsSpaceID) if err != nil { - log.Fatal("error initializing mdc:", err) + return err } for _, p := range []string{ @@ -73,13 +109,12 @@ func NewMetadataClient(cfg *config.Config) MetadataClient { bundleFolderLocation, valuesFolderLocation, } { - err = mdc.MakeDirIfNotExist(nil, p) + err = s.mdc.MakeDirIfNotExist(nil, p) if err != nil { - log.Fatalf("error creating settings folder '%s': %s", p, err) + return err } } - return mdc - + return nil } func init() { diff --git a/settings/pkg/store/metadata/store_test.go b/settings/pkg/store/metadata/store_test.go index 326ca6476..c42f3d027 100644 --- a/settings/pkg/store/metadata/store_test.go +++ b/settings/pkg/store/metadata/store_test.go @@ -95,7 +95,12 @@ func (m *MockedMetadataClient) ReadDir(_ context.Context, id string) ([]string, } // MakeDirIfNotExist does nothing -func (m *MockedMetadataClient) MakeDirIfNotExist(_ context.Context, id string) error { +func (*MockedMetadataClient) MakeDirIfNotExist(_ context.Context, _ string) error { + return nil +} + +// Init does nothing +func (*MockedMetadataClient) Init(_ context.Context, _ string) error { return nil } diff --git a/settings/pkg/store/metadata/values.go b/settings/pkg/store/metadata/values.go index 50421b5d5..4f7c23c53 100644 --- a/settings/pkg/store/metadata/values.go +++ b/settings/pkg/store/metadata/values.go @@ -19,6 +19,7 @@ func (s Store) ListValues(bundleID, accountUUID string) ([]*settingsmsg.Value, e // ReadValue tries to find a value by the given valueId within the dataPath func (s Store) ReadValue(valueID string) (*settingsmsg.Value, error) { + s.Init() b, err := s.mdc.SimpleDownload(nil, valuePath(valueID)) if err != nil { return nil, err @@ -34,6 +35,7 @@ func (s Store) ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*set // WriteValue writes the given value into a file within the dataPath func (s Store) WriteValue(value *settingsmsg.Value) (*settingsmsg.Value, error) { + s.Init() b, err := json.Marshal(value) if err != nil { return nil, err