11"""Support for working with the internal data store and the strucutured
22resources that the internal store holds.
33"""
4- from typing import Collection , Tuple , Type , TypeVar
4+ from typing import Collection , Tuple , Type , TypeVar , Union
55
66from . import resources
77from .enums import ConfigNS , State
1010 ConfigStore ,
1111 ConfigStoreListing ,
1212 EntryKey ,
13+ ResourceKey ,
1314 Self ,
1415 Simplifiable ,
1516)
1920T = TypeVar ('T' )
2021
2122
22- def cluster_key (cluster_id : str ) -> EntryKey :
23- """Return store entry key for a cluster entry."""
24- return str (ConfigNS .CLUSTERS ), cluster_id
23+ class ResourceIDKey :
24+ """A ResourceKey for resources with only one ID."""
2525
26+ def __init__ (self , resource_id : str ) -> None :
27+ self .resource_id = resource_id
2628
27- def share_key (cluster_id : str , share_id : str ) -> EntryKey :
28- """Return store entry key for a share entry."""
29- return str (ConfigNS .SHARES ), f'{ cluster_id } .{ share_id } '
29+ def __str__ (self ) -> str :
30+ return self .resource_id
3031
3132
32- def join_auth_key (auth_id : str ) -> EntryKey :
33- """Return store entry key for a join auth entry."""
34- return str (ConfigNS .JOIN_AUTHS ), auth_id
33+ class ChildResourceIDKey :
34+ """A ResourceKey for resources with both a parent and child ID."""
3535
36+ def __init__ (self , parent_id : str , resource_id : str ) -> None :
37+ self .parent_id = parent_id
38+ self .resource_id = resource_id
39+ self ._key = f'{ parent_id } .{ resource_id } '
3640
37- def users_and_groups_key (users_groups_id : str ) -> EntryKey :
38- """Return store entry key for a users-and-groups entry."""
39- return str (ConfigNS .USERS_AND_GROUPS ), users_groups_id
40-
41-
42- def resource_key (resource : SMBResource ) -> EntryKey :
43- """Return a store entry key for an smb resource object."""
44- if isinstance (resource , (resources .Cluster , resources .RemovedCluster )):
45- return cluster_key (resource .cluster_id )
46- elif isinstance (resource , (resources .Share , resources .RemovedShare )):
47- return share_key (resource .cluster_id , resource .share_id )
48- elif isinstance (resource , resources .JoinAuth ):
49- return join_auth_key (resource .auth_id )
50- elif isinstance (resource , resources .UsersAndGroups ):
51- return users_and_groups_key (resource .users_groups_id )
52- raise TypeError ('not a valid smb resource' )
41+ def __str__ (self ) -> str :
42+ return self ._key
5343
5444
5545class ResourceEntry :
@@ -70,7 +60,7 @@ def get(self) -> SMBResource:
7060
7161 def get_resource_type (self , cls : Type [T ]) -> T :
7262 obj = self .get ()
73- assert isinstance (obj , cls )
63+ assert isinstance (obj , cls ), f" { obj !r } is not a { cls } "
7464 return obj
7565
7666 def set (self , resource : Simplifiable ) -> None :
@@ -90,20 +80,49 @@ def create_or_update(self, resource: Simplifiable) -> State:
9080 def remove (self ) -> bool :
9181 return self .config_entry .remove ()
9282
83+ @classmethod
84+ def ids (
85+ cls , store : ConfigStoreListing
86+ ) -> Union [Collection [str ], Collection [Tuple [str , str ]]]:
87+ raise NotImplementedError ()
9388
94- class ClusterEntry (ResourceEntry ):
95- """Cluster resource getter/setter for the smb internal data store(s)."""
89+ @classmethod
90+ def from_store_by_key (
91+ cls , store : ConfigStore , key : Union [str , ResourceKey ]
92+ ) -> Self :
93+ _key = str (key )
94+ return cls (_key , store [str (cls .namespace ), _key ])
95+
96+ @classmethod
97+ def to_key (cls , resource : SMBResource ) -> ResourceKey :
98+ raise NotImplementedError ()
9699
97- namespace = ConfigNS .CLUSTERS
100+
101+ class CommonResourceEntry (ResourceEntry ):
102+ """Common resource getter/setter for objects with a single ID value in the
103+ smb internal data store(s).
104+ """
98105
99106 @classmethod
100- def from_store (cls , store : ConfigStore , cluster_id : str ) -> Self :
101- return cls ( cluster_id , store [ str ( cls . namespace ), cluster_id ] )
107+ def from_store (cls , store : ConfigStore , resource_id : str ) -> Self :
108+ return cls . from_store_by_key ( store , resource_id )
102109
103110 @classmethod
104111 def ids (cls , store : ConfigStoreListing ) -> Collection [str ]:
105112 return store .contents (str (cls .namespace ))
106113
114+
115+ class ClusterEntry (CommonResourceEntry ):
116+ """Cluster resource getter/setter for the smb internal data store(s)."""
117+
118+ namespace = ConfigNS .CLUSTERS
119+ _for_resource = (resources .Cluster , resources .RemovedCluster )
120+
121+ @classmethod
122+ def to_key (cls , resource : SMBResource ) -> ResourceKey :
123+ assert isinstance (resource , cls ._for_resource )
124+ return ResourceIDKey (resource .cluster_id )
125+
107126 def get_cluster (self ) -> resources .Cluster :
108127 return self .get_resource_type (resources .Cluster )
109128
@@ -112,73 +131,92 @@ class ShareEntry(ResourceEntry):
112131 """Share resource getter/setter for the smb internal data store(s)."""
113132
114133 namespace = ConfigNS .SHARES
134+ _for_resource = (resources .Share , resources .RemovedShare )
115135
116136 @classmethod
117137 def from_store (
118138 cls , store : ConfigStore , cluster_id : str , share_id : str
119139 ) -> Self :
120- key = f' { cluster_id } . { share_id } '
121- return cls ( key , store [ str (cls . namespace ), key ] )
140+ key = ChildResourceIDKey ( cluster_id , share_id )
141+ return cls . from_store_by_key ( store , str (key ) )
122142
123143 @classmethod
124144 def ids (cls , store : ConfigStoreListing ) -> Collection [Tuple [str , str ]]:
125145 return [_split (k ) for k in store .contents (str (cls .namespace ))]
126146
147+ @classmethod
148+ def to_key (cls , resource : SMBResource ) -> ResourceKey :
149+ assert isinstance (resource , cls ._for_resource )
150+ return ChildResourceIDKey (resource .cluster_id , resource .share_id )
151+
127152 def get_share (self ) -> resources .Share :
128153 return self .get_resource_type (resources .Share )
129154
130155
131- class JoinAuthEntry (ResourceEntry ):
156+ class JoinAuthEntry (CommonResourceEntry ):
132157 """JoinAuth resource getter/setter for the smb internal data store(s)."""
133158
134159 namespace = ConfigNS .JOIN_AUTHS
160+ _for_resource = resources .JoinAuth
135161
136162 @classmethod
137- def from_store (cls , store : ConfigStore , auth_id : str ) -> Self :
138- return cls (auth_id , store [str (cls .namespace ), auth_id ])
139-
140- @classmethod
141- def ids (cls , store : ConfigStoreListing ) -> Collection [str ]:
142- return store .contents (str (cls .namespace ))
163+ def to_key (cls , resource : SMBResource ) -> ResourceKey :
164+ assert isinstance (resource , cls ._for_resource )
165+ return ResourceIDKey (resource .auth_id )
143166
144167 def get_join_auth (self ) -> resources .JoinAuth :
145168 return self .get_resource_type (resources .JoinAuth )
146169
147170
148- class UsersAndGroupsEntry (ResourceEntry ):
171+ class UsersAndGroupsEntry (CommonResourceEntry ):
149172 """UsersAndGroupsEntry resource getter/setter for the smb internal data
150173 store(s).
151174 """
152175
153176 namespace = ConfigNS .USERS_AND_GROUPS
177+ _for_resource = resources .UsersAndGroups
154178
155179 @classmethod
156- def from_store (cls , store : ConfigStore , auth_id : str ) -> Self :
157- return cls (auth_id , store [str (cls .namespace ), auth_id ])
158-
159- @classmethod
160- def ids (cls , store : ConfigStoreListing ) -> Collection [str ]:
161- return store .contents (str (cls .namespace ))
180+ def to_key (cls , resource : SMBResource ) -> ResourceKey :
181+ assert isinstance (resource , cls ._for_resource )
182+ return ResourceIDKey (resource .users_groups_id )
162183
163184 def get_users_and_groups (self ) -> resources .UsersAndGroups :
164185 return self .get_resource_type (resources .UsersAndGroups )
165186
166187
188+ def _map_resource_entry (
189+ resource : Union [SMBResource , Type [SMBResource ]]
190+ ) -> Type [ResourceEntry ]:
191+ rcls = resource if isinstance (resource , type ) else type (resource )
192+ _map = {
193+ resources .Cluster : ClusterEntry ,
194+ resources .RemovedCluster : ClusterEntry ,
195+ resources .Share : ShareEntry ,
196+ resources .RemovedShare : ShareEntry ,
197+ resources .JoinAuth : JoinAuthEntry ,
198+ resources .UsersAndGroups : UsersAndGroupsEntry ,
199+ }
200+ try :
201+ return _map [rcls ]
202+ except KeyError :
203+ raise TypeError ('not a valid smb resource' )
204+
205+
167206def resource_entry (
168207 store : ConfigStore , resource : SMBResource
169208) -> ResourceEntry :
170209 """Return a bound store entry object given a resource object."""
171- if isinstance (resource , (resources .Cluster , resources .RemovedCluster )):
172- return ClusterEntry .from_store (store , resource .cluster_id )
173- elif isinstance (resource , (resources .Share , resources .RemovedShare )):
174- return ShareEntry .from_store (
175- store , resource .cluster_id , resource .share_id
176- )
177- elif isinstance (resource , resources .JoinAuth ):
178- return JoinAuthEntry .from_store (store , resource .auth_id )
179- elif isinstance (resource , resources .UsersAndGroups ):
180- return UsersAndGroupsEntry .from_store (store , resource .users_groups_id )
181- raise TypeError ('not a valid smb resource' )
210+ entry_cls = _map_resource_entry (resource )
211+ key = entry_cls .to_key (resource )
212+ return entry_cls .from_store_by_key (store , key )
213+
214+
215+ def resource_key (resource : SMBResource ) -> EntryKey :
216+ """Return a store entry key for an smb resource object."""
217+ entry_cls = _map_resource_entry (resource )
218+ key = entry_cls .to_key (resource )
219+ return str (entry_cls .namespace ), str (key )
182220
183221
184222def _split (share_key : str ) -> Tuple [str , str ]:
0 commit comments