@@ -3,6 +3,8 @@ package internalstorage
33import (
44 "context"
55 "fmt"
6+ "strings"
7+ "sync"
68
79 "gorm.io/gorm"
810 "k8s.io/apimachinery/pkg/runtime/schema"
@@ -12,30 +14,14 @@ import (
1214)
1315
1416type StorageFactory struct {
15- db * gorm.DB
16- AutoMigration * bool
17- DivisionPolicy DivisionPolicy
18- Mapper []ResourceMapper
17+ sync.Mutex
18+
19+ db * gorm.DB
20+ SkipAutoMigration bool
21+ DivisionPolicy DivisionPolicy
1922}
2023
2124func (s * StorageFactory ) AutoMigrate () error {
22- if s .AutoMigration != nil && * s .AutoMigration {
23- switch s.DivisionPolicy {
24- if err := s .db .AutoMigrate (& Resource {}); err != nil {
25- return err
26- }
27- case "" , DivisionPolicyNone :
28- case DivisionPolicyGroupResource :
29-
30- }
31-
32- if s .DivisionPolicy == "" || s .DivisionPolicy == DivisionPolicyNone {
33- if err := s .db .AutoMigrate (& Resource {}); err != nil {
34- return err
35- }
36- }
37- }
38-
3925 return nil
4026}
4127
@@ -44,10 +30,47 @@ func (s *StorageFactory) GetSupportedRequestVerbs() []string {
4430}
4531
4632func (s * StorageFactory ) NewResourceStorage (config * storage.ResourceStorageConfig ) (storage.ResourceStorage , error ) {
47- return & ResourceStorage {
48- db : s .db ,
49- codec : config .Codec ,
33+ s .Lock ()
34+ defer s .Unlock ()
5035
36+ gvr := schema.GroupVersionResource {
37+ Group : config .StorageGroupResource .Group ,
38+ Version : config .StorageVersion .Version ,
39+ Resource : config .StorageGroupResource .Resource ,
40+ }
41+ table := s .tableName (gvr )
42+
43+ var model interface {}
44+ switch s .DivisionPolicy {
45+ case DivisionPolicyGroupResource :
46+ model = & GroupVersionResource {}
47+ if ! s .SkipAutoMigration {
48+ if exist := s .db .Migrator ().HasTable (table ); ! exist {
49+ if err := s .db .AutoMigrate (& GroupVersionResource {}); err != nil {
50+ return nil , err
51+ }
52+
53+ err := s .db .Migrator ().RenameTable ("groupversionresources" , table )
54+ if err != nil {
55+ return nil , err
56+ }
57+ }
58+ }
59+ case "" , DivisionPolicyNone :
60+ model = & Resource {}
61+ if ! s .SkipAutoMigration {
62+ if exist := s .db .Migrator ().HasTable (table ); ! exist {
63+ if err := s .db .AutoMigrate (& Resource {}); err != nil {
64+ return nil , err
65+ }
66+ }
67+ }
68+ }
69+
70+ return & ResourceStorage {
71+ db : s .db .Table (table ).Model (model ),
72+ model : model ,
73+ codec : config .Codec ,
5174 storageGroupResource : config .StorageGroupResource ,
5275 storageVersion : config .StorageVersion ,
5376 memoryVersion : config .MemoryVersion ,
@@ -64,12 +87,24 @@ func (s *StorageFactory) NewCollectionResourceStorage(cr *internal.CollectionRes
6487}
6588
6689func (s * StorageFactory ) GetResourceVersions (ctx context.Context , cluster string ) (map [schema.GroupVersionResource ]map [string ]interface {}, error ) {
90+ s .Lock ()
91+ tables , err := s .db .Migrator ().GetTables ()
92+ if err != nil {
93+ s .Unlock ()
94+ return nil , err
95+ }
96+ s .Unlock ()
97+
6798 var resources []Resource
68- result := s .db .WithContext (ctx ).Select ("group" , "version" , "resource" , "namespace" , "name" , "resource_version" ).
69- Where (map [string ]interface {}{"cluster" : cluster }).
70- Find (& resources )
71- if result .Error != nil {
72- return nil , InterpretDBError (cluster , result .Error )
99+ for _ , table := range tables {
100+ result := s .db .WithContext (ctx ).
101+ Table (table ).
102+ Select ("group" , "version" , "resource" , "namespace" , "name" , "resource_version" ).
103+ Where (map [string ]interface {}{"cluster" : cluster }).
104+ Find (& resources )
105+ if result .Error != nil {
106+ return nil , InterpretDBError (cluster , result .Error )
107+ }
73108 }
74109
75110 resourceversions := make (map [schema.GroupVersionResource ]map [string ]interface {})
@@ -91,18 +126,44 @@ func (s *StorageFactory) GetResourceVersions(ctx context.Context, cluster string
91126}
92127
93128func (s * StorageFactory ) CleanCluster (ctx context.Context , cluster string ) error {
94- result := s .db .WithContext (ctx ).Where (map [string ]interface {}{"cluster" : cluster }).Delete (& Resource {})
95- return InterpretDBError (cluster , result .Error )
129+ s .Lock ()
130+ tables , err := s .db .Migrator ().GetTables ()
131+ if err != nil {
132+ s .Unlock ()
133+ return err
134+ }
135+ s .Unlock ()
136+
137+ for _ , table := range tables {
138+ result := s .db .WithContext (ctx ).Table (table ).Where (map [string ]interface {}{"cluster" : cluster }).Delete (& Resource {})
139+ if result .Error != nil {
140+ return InterpretDBError (cluster , result .Error )
141+ }
142+ }
143+
144+ return nil
96145}
97146
98147func (s * StorageFactory ) CleanClusterResource (ctx context.Context , cluster string , gvr schema.GroupVersionResource ) error {
99- result := s .db .WithContext (ctx ).Where (map [string ]interface {}{
100- "cluster" : cluster ,
101- "group" : gvr .Group ,
102- "version" : gvr .Version ,
103- "resource" : gvr .Resource ,
104- }).Delete (& Resource {})
105- return InterpretDBError (fmt .Sprintf ("%s/%s" , cluster , gvr ), result .Error )
148+ err := s .db .Transaction (func (db * gorm.DB ) error {
149+ result := s .db .WithContext (ctx ).
150+ Table (s .tableName (gvr )).
151+ Where (map [string ]interface {}{
152+ "cluster" : cluster ,
153+ "group" : gvr .Group ,
154+ "version" : gvr .Version ,
155+ "resource" : gvr .Resource ,
156+ }).
157+ Delete (& Resource {})
158+
159+ if result .Error != nil {
160+ return result .Error
161+ }
162+
163+ return nil
164+ })
165+
166+ return InterpretDBError (fmt .Sprintf ("%s/%s" , cluster , gvr ), err )
106167}
107168
108169func (s * StorageFactory ) GetCollectionResources (ctx context.Context ) ([]* internal.CollectionResource , error ) {
@@ -116,3 +177,22 @@ func (s *StorageFactory) GetCollectionResources(ctx context.Context) ([]*interna
116177func (s * StorageFactory ) PrepareCluster (cluster string ) error {
117178 return nil
118179}
180+
181+ // GenerateTableFor return table name using gvr string
182+ func GenerateTableFor (gvr schema.GroupVersionResource ) string {
183+ if gvr .Group == "" {
184+ return fmt .Sprintf ("%s_%s" , gvr .Version , gvr .Resource )
185+ }
186+
187+ group := strings .ReplaceAll (gvr .Group , "." , "_" )
188+ return fmt .Sprintf ("%s_%s_%s" , group , gvr .Version , gvr .Resource )
189+ }
190+
191+ func (s * StorageFactory ) tableName (gvr schema.GroupVersionResource ) string {
192+ table := "resources"
193+ if s .DivisionPolicy == DivisionPolicyGroupResource {
194+ table = GenerateTableFor (gvr )
195+ }
196+
197+ return table
198+ }
0 commit comments