Ticket #136: extensible_config_v2.patch
| File extensible_config_v2.patch, 19.2 KB (added by callan@…, 3 years ago) |
|---|
-
config.py
20 20 import copy 21 21 22 22 from twisted.python import log 23 from twisted.python.reflect import namedClass 23 24 24 25 from twistedcaldav.py.plistlib import readPlist 25 26 27 def _loadDirectoryService(klass): 28 """ 29 Loads a directory service class at runtime, raising a ConfigurationError 30 on failure. 31 """ 32 try: 33 return namedClass(klass) 34 except (ImportError, AttributeError): 35 raise ConfigurationError( 36 "Unable to load directory service %s" % klass) 37 26 38 defaultConfigFile = "/etc/caldavd/caldavd.plist" 27 39 28 serviceDefaultParams = { 29 "twistedcaldav.directory.xmlfile.XMLDirectoryService": { 30 "xmlFile": "/etc/caldavd/accounts.xml", 31 }, 32 "twistedcaldav.directory.appleopendirectory.OpenDirectoryService": { 33 "node": "/Search", 34 "requireComputerRecord": True, 35 }, 36 } 40 defaultDirectoryService = \ 41 "twistedcaldav.directory.xmlfile.XMLDirectoryService" 37 42 43 defaultDirectoryServiceParams = \ 44 copy.deepcopy(_loadDirectoryService(defaultDirectoryService).defaultParams) 45 38 46 defaultConfig = { 39 47 # 40 48 # Public network address information … … 75 83 # users, groups, locations and resources) to the server. 76 84 # 77 85 "DirectoryService": { 78 "type": "twistedcaldav.directory.xmlfile.XMLDirectoryService",79 "params": serviceDefaultParams["twistedcaldav.directory.xmlfile.XMLDirectoryService"],86 "type": defaultDirectoryService, 87 "params": defaultDirectoryServiceParams, 80 88 }, 81 89 82 90 # … … 189 197 return str(self._data) 190 198 191 199 def update(self, items): 200 dsData = self._data["DirectoryService"] 192 201 dsType = items.get("DirectoryService", {}).get("type", None) 193 202 if dsType is None: 194 dsType = self._data["DirectoryService"]["type"] 195 else: 196 if dsType == self._data["DirectoryService"]["type"]: 197 oldParams = self._data["DirectoryService"]["params"] 198 newParams = items["DirectoryService"].get("params", {}) 199 _mergeData(oldParams, newParams) 200 else: 201 if dsType in serviceDefaultParams: 202 self._data["DirectoryService"]["params"] = copy.deepcopy(serviceDefaultParams[dsType]) 203 else: 204 self._data["DirectoryService"]["params"] = {} 203 dsType = dsData["type"] 204 dsClass = _loadDirectoryService(dsType) 205 205 206 # Copy the default parameters from the directory service class, if the 207 # directory service we've been given is different than the one we 208 # already have. This ensures that at the very least the directory 209 # service is configured using the specified defaults and that the 210 # update method may be called more than once with specific parameters 211 # for configuration. 212 try: 213 if dsData["type"] != dsType: 214 dsData["type"] = dsType 215 dsData["params"] = copy.deepcopy(dsClass.defaultParams) 216 except AttributeError: 217 raise ConfigurationError( 218 "Default service parameters must be specified in %s " \ 219 "using the 'defaultParams' class variable." % dsType) 220 # Ensure that the parameters defined in the configuration file are 221 # acceptable for the directory service. 206 222 for param in items.get("DirectoryService", {}).get("params", {}): 207 if param not in serviceDefaultParams[dsType]: 208 raise ConfigurationError("Parameter %s is not supported by service %s" % (param, dsType)) 223 if param not in dsClass.defaultParams: 224 raise ConfigurationError( 225 "Parameter %s is not supported by service %s" % \ 226 (param, dsType)) 209 227 210 228 _mergeData(self._data, items) 211 229 212 for param in tuple(self._data["DirectoryService"]["params"]): 213 if param not in serviceDefaultParams[self._data["DirectoryService"]["type"]]: 214 del self._data["DirectoryService"]["params"][param] 230 # Cleeanup parameters which may have been left around after a switch 231 # in directory service type. 232 for param in tuple(dsData["params"]): 233 if param not in dsClass.defaultParams: 234 del dsData["params"][param] 215 235 216 236 self.updateServerCapabilities() 217 237 -
directory/xmlfile.py
39 39 40 40 realmName = None 41 41 42 defaultParams = { 43 "xmlFile": "/etc/caldavd/accounts.xml", 44 } 45 42 46 def __repr__(self): 43 47 return "<%s %r: %r>" % (self.__class__.__name__, self.realmName, self.xmlFile) 44 48 -
directory/sqldb.py
285 285 baseGUID = "8256E464-35E0-4DBB-A99C-F0E30C231675" 286 286 realmName = None 287 287 288 defaultParams = { 289 "dbParentPath": "twistedcaldav/test/data/", 290 "xmlFile": None 291 } 292 288 293 def __repr__(self): 289 294 return "<%s %r: %r>" % (self.__class__.__name__, self.realmName, self.manager.dbpath) 290 295 -
directory/appleopendirectory.py
56 56 """ 57 57 baseGUID = "891F8321-ED02-424C-BA72-89C32F215C1E" 58 58 59 defaultParams = { 60 "node": "/Search", 61 "requireComputerRecord": True, 62 } 63 59 64 def __repr__(self): 60 65 return "<%s %r: %r>" % (self.__class__.__name__, self.realmName, self.node) 61 66 -
directory/idirectory.py
34 34 realmName = Attribute("The name of the authentication realm this service represents.") 35 35 guid = Attribute("A GUID for this service.") 36 36 37 defaultParams = Attribute("Default configuration parameters for this service.") 38 37 39 def recordTypes(): 38 40 """ 39 41 @return: a sequence of strings denoting the record types that are kept -
directory/apache.py
37 37 """ 38 38 Abstract Apache-compatible implementation of L{IDirectoryService}. 39 39 """ 40 41 defaultParams = { 42 "realmName": "example.com", 43 "userFile": "/etc/caldavd/basic", 44 "groupFile": None, 45 } 46 40 47 def __repr__(self): 41 48 return "<%s %r: %r %r>" % (self.__class__.__name__, self.realmName, self.userFile, self.groupFile) 42 49 -
test/test_config.py
21 21 from twistedcaldav.py.plistlib import writePlist 22 22 23 23 from twistedcaldav.config import config, defaultConfig, ConfigurationError 24 from twistedcaldav.directory.directory import DirectoryService 24 25 25 26 testConfig = """<?xml version="1.0" encoding="UTF-8"?> 26 27 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> … … 34 35 </plist> 35 36 """ 36 37 38 XML_DIRECTORY_SERVICE = \ 39 "twistedcaldav.directory.xmlfile.XMLDirectoryService" 40 41 OPEN_DIRECTORY_SERVICE = \ 42 "twistedcaldav.directory.appleopendirectory.OpenDirectoryService" 43 44 SQL_DIRECTORY_SERVICE = \ 45 "twistedcaldav.directory.sqldb.SQLDirectoryService" 46 47 APACHE_BASIC_DIRECTORY_SERVICE = \ 48 "twistedcaldav.directory.apache.BasicDirectoryService" 49 50 APACHE_DIGEST_DIRECTORY_SERVICE = \ 51 "twistedcaldav.directory.apache.DigestDirectoryService" 52 53 SUPER_DUPER_DIRECTORY_SERVICE = \ 54 "twistedcaldav.test.test_config.SuperDuperService" 55 56 class SuperDuperService(DirectoryService): 57 """ 58 A super duper directory service that's super duper effective at being 59 used for testing but not awesome. 60 """ 61 defaultParams = { 62 "superLevel": "super", 63 "duperLevel": "duper", 64 } 65 37 66 def _testVerbose(testCase): 38 67 from twistedcaldav.config import config 39 68 testCase.assertEquals(config.Verbose, True) … … 44 73 config.update(defaultConfig) 45 74 self.testConfig = self.mktemp() 46 75 open(self.testConfig, 'w').write(testConfig) 76 self.ds = config.DirectoryService 47 77 48 78 def tearDown(self): 49 79 config.setDefaults(defaultConfig) 50 80 config.loadConfig(None) 51 81 config.reload() 52 82 83 def _checkXMLDefaults(self): 84 """ 85 Checks that the base XML directory service defaults are correct. 86 """ 87 self.assertEquals(self.ds["type"], XML_DIRECTORY_SERVICE) 88 self.assertEquals(self.ds["params"]["xmlFile"], 89 "/etc/caldavd/accounts.xml") 90 91 def _checkODDefaults(self): 92 """ 93 Checks that the base Apple open directory service defaults are correct. 94 """ 95 self.assertEquals(self.ds["type"], OPEN_DIRECTORY_SERVICE) 96 self.assertNotIn("xmlFile", self.ds["params"]) 97 self.assertEquals(self.ds["params"]["node"], "/Search") 98 self.assertEquals(self.ds["params"]["requireComputerRecord"], True) 99 100 def _checkSQLDefaults(self): 101 """ 102 Checks that the base SQL directory service defaults are correct. 103 """ 104 self.assertEquals(self.ds["type"], SQL_DIRECTORY_SERVICE) 105 self.assertEquals(self.ds["params"]["dbParentPath"], 106 "twistedcaldav/test/data/") 107 self.assertEquals(self.ds["params"]["xmlFile"], None) 108 109 def _checkApacheBaseDefaults(self): 110 """ 111 Checks that the base Apache open directory service parameters are correct. 112 """ 113 self.assertEquals(self.ds["params"]["realmName"], "example.com") 114 self.assertEquals(self.ds["params"]["userFile"], "/etc/caldavd/basic") 115 self.assertEquals(self.ds["params"]["groupFile"], None) 116 117 def _checkApacheBasicDefaults(self): 118 """ 119 Checks that the base Apache basic authentication directory service 120 defaults are correct. 121 """ 122 self.assertEquals(self.ds["type"], APACHE_BASIC_DIRECTORY_SERVICE) 123 self.assertNotIn("xmlFile", self.ds["params"]) 124 self._checkApacheBaseDefaults() 125 126 def _checkApacheDigestDefaults(self): 127 """ 128 Checks that the base Apache digest authentication directory service 129 defaults are correct. 130 """ 131 self.assertEquals(self.ds["type"], APACHE_DIGEST_DIRECTORY_SERVICE) 132 self.assertNotIn("xmlFile", self.ds["params"]) 133 self._checkApacheBaseDefaults() 134 135 def _checkSuperDuperDefaults(self): 136 """ 137 Checks that the base super duper test-only directory service defaults 138 are correct. 139 """ 140 self.assertEquals(self.ds["type"], SUPER_DUPER_DIRECTORY_SERVICE) 141 self.assertNotIn("xmlFile", self.ds["params"]) 142 self.assertEquals(self.ds["params"]["superLevel"], "super") 143 self.assertEquals(self.ds["params"]["duperLevel"], "duper") 144 53 145 def testDefaults(self): 54 146 for key, value in defaultConfig.iteritems(): 55 147 self.assertEquals(getattr(config, key), value) … … 121 213 122 214 self.assertEquals(config.MultiProcess["LoadBalancer"]["Enabled"], True) 123 215 216 def testDirectoryService_loadSQL(self): 217 self._checkXMLDefaults() 218 config.update({"DirectoryService": {"type": SQL_DIRECTORY_SERVICE}}) 219 self._checkSQLDefaults() 220 221 def testDirectoryService_loadApacheBasic(self): 222 self._checkXMLDefaults() 223 config.update({ 224 "DirectoryService": { 225 "type": APACHE_BASIC_DIRECTORY_SERVICE 226 } 227 }) 228 self._checkApacheBasicDefaults() 229 230 def testDirectoryService_loadApacheDigest(self): 231 self._checkXMLDefaults() 232 config.update({ 233 "DirectoryService": { 234 "type": APACHE_DIGEST_DIRECTORY_SERVICE 235 } 236 }) 237 self._checkApacheDigestDefaults() 238 124 239 def testDirectoryService_noChange(self): 125 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService") 126 self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml") 127 240 self._checkXMLDefaults() 128 241 config.update({"DirectoryService": {}}) 242 self._checkXMLDefaults() 129 243 130 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService")131 self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml")132 133 244 def testDirectoryService_sameType(self): 134 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService") 135 self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml") 245 self._checkXMLDefaults() 246 config.update({"DirectoryService": {"type": XML_DIRECTORY_SERVICE}}) 247 self._checkXMLDefaults() 136 248 137 config.update({"DirectoryService": {"type": "twistedcaldav.directory.xmlfile.XMLDirectoryService"}})138 139 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService")140 self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml")141 142 249 def testDirectoryService_newType(self): 143 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService") 144 self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml") 250 self._checkXMLDefaults() 251 config.update({ 252 "DirectoryService": { 253 "type": SUPER_DUPER_DIRECTORY_SERVICE 254 } 255 }) 256 self._checkSuperDuperDefaults() 145 257 146 config.update({"DirectoryService": {"type": "twistedcaldav.directory.appleopendirectory.OpenDirectoryService"}})147 148 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.appleopendirectory.OpenDirectoryService")149 self.assertNotIn("xmlFile", config.DirectoryService["params"])150 self.assertEquals(config.DirectoryService["params"]["node"], "/Search")151 self.assertEquals(config.DirectoryService["params"]["requireComputerRecord"], True)152 153 258 def testDirectoryService_newParam(self): 154 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService") 155 self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml") 259 self._checkXMLDefaults() 260 config.update({ 261 "DirectoryService": { 262 "type": SUPER_DUPER_DIRECTORY_SERVICE 263 } 264 }) 265 config.update({ 266 "DirectoryService": { 267 "params": {"superLevel": "!super" } 268 } 269 }) 270 self.assertEquals(self.ds["type"], SUPER_DUPER_DIRECTORY_SERVICE) 271 self.assertNotIn("xmlFile", self.ds["params"]) 272 self.assertEquals(self.ds["params"]["superLevel"], "!super") 273 self.assertEquals(self.ds["params"]["duperLevel"], "duper") 274 275 def testDirectoryService_newBadParam(self): 276 self._checkXMLDefaults() 277 self.assertRaises(ConfigurationError, config.update, { 278 "DirectoryService": { 279 "type": SUPER_DUPER_DIRECTORY_SERVICE, 280 "params": { 281 "xmlFile": "/etc/caldavd/accounts.xml" 282 } 283 } 284 }) 285 286 def testDirectoryService_twoNewParams(self): 287 self._checkXMLDefaults() 288 config.update({ 289 "DirectoryService": { 290 "type": SUPER_DUPER_DIRECTORY_SERVICE 291 } 292 }) 293 config.update({ 294 "DirectoryService": { 295 "params": {"superLevel": "!super" } 296 } 297 }) 298 config.update({ 299 "DirectoryService": { 300 "params": {"duperLevel": "!duper" } 301 } 302 }) 303 self.assertEquals(self.ds["type"], SUPER_DUPER_DIRECTORY_SERVICE) 304 self.assertNotIn("xmlFile", self.ds["params"]) 305 self.assertEquals(self.ds["params"]["superLevel"], "!super") 306 self.assertEquals(self.ds["params"]["duperLevel"], "!duper") 156 307 157 config.update({"DirectoryService": {"type": "twistedcaldav.directory.appleopendirectory.OpenDirectoryService"}}) 158 config.update({"DirectoryService": {"params": {"requireComputerRecord": False}}}) 308 def testDirectoryService_newTypeOD(self): 309 self._checkXMLDefaults() 310 config.update({"DirectoryService": {"type": OPEN_DIRECTORY_SERVICE}}) 311 self._checkODDefaults() 159 312 160 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.appleopendirectory.OpenDirectoryService") 161 self.assertEquals(config.DirectoryService["params"]["node"], "/Search") 162 self.assertEquals(config.DirectoryService["params"]["requireComputerRecord"], False) 313 def testDirectoryService_newParamOD(self): 314 self._checkXMLDefaults() 315 config.update({"DirectoryService": {"type": OPEN_DIRECTORY_SERVICE}}) 316 config.update({ 317 "DirectoryService": { 318 "params": {"requireComputerRecord": False} 319 } 320 }) 321 self.assertEquals(self.ds["type"], OPEN_DIRECTORY_SERVICE) 322 self.assertEquals(self.ds["params"]["node"], "/Search") 323 self.assertEquals(self.ds["params"]["requireComputerRecord"], False) 163 324 164 325 def testDirectoryService_badParam(self): 165 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService") 166 self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml") 326 self._checkXMLDefaults() 327 self.assertRaises(ConfigurationError, config.update, { 328 "DirectoryService": { 329 "params": {"requireComputerRecord": False} 330 } 331 }) 167 332 168 self.assertRaises(ConfigurationError, config.update, {"DirectoryService": {"params": {"requireComputerRecord": False}}})169 170 333 def testDirectoryService_unknownType(self): 171 self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService") 172 self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml") 334 self._checkXMLDefaults() 335 self.assertRaises(ConfigurationError, config.update, { 336 "DirectoryService": { 337 "type": "twistedcaldav.test.test_config.SuperDuperAwesomeService" 338 } 339 }) 173 340 174 config.update({"DirectoryService": {"type": "twistedcaldav.test.test_config.SuperDuperAwesomeService"}})175 176 self.assertEquals(177 config.DirectoryService["params"],178 SuperDuperAwesomeService.defaultParameters179 )180 181 testDirectoryService_unknownType.todo = "unimplemented"182 183 341 def testUpdateDefaults(self): 184 342 self.assertEquals(config.SSLPort, 0) 185 343
