It would be nice to be able to give WvConf? "subdirectories" - for example, so that user account entries don't need to be split among multiple sections. Instead, you could have
/users/apenwarr/uid = 1001 /users/apenwarr/fullname = Avery Pennarun /users/apenwarr/password = blah
...and so on for each user. Exactly how it would be stored in the file is another question - the above is obviously a bit redundant.
It would be really nice if we could then do recursive wildcard/regex queries on the config file. For example, to pull out the list of all uids, we could ask for an iterator on "/users/*/uid".
...
Interestingly, LDAP looks like it does almost exactly what we want already. We just need to make a WvConfEmu? front end for it :)
For more interesting information, see:
This will put us on the way to LifeCluster? too, since partial config file replication (especially user accounts) is one of the hardest parts. We could also use it for sharing NetMap? and dns entries between weavers on a LAN.
apenwarr (2002/02/19):
Specific things I want from the new UniConf (this is mainly for my own reference :)):
- Smarter iterators: done; we have UniConf::Iter, RecursiveIter?, and XIter that let us do various clever things.
- "Section" objects can do anything a top-level WvConf? object can do: load/save, search, iterate, create subsections.
WvString? s = cfg["Users"]["apenwarr"]["name"]should work. Ideallycfg["users/apenwarr/name"]should work too.cfg["Users"].save("/tmp/users.cfg")should let us save a subsection to a file. Anything that normally takes a WvConf?& should be able to take a subsection instead, so classes can own a subtree of the config when they're in Weaver?, and the entire file when they're not.- This is working! A UniConf object can be a root, subtree, or entry. UniConfGen objects can own a subtree and implement things like load and save.
- Multiple backends:
- we definitely need a plaintext one (maybe even an old-WvConf? compatible one, ie. with sections named
users/apenwarr.- UniConfIniFile? works, and you can tie more than one of them together to form an especially funky tree.
- An LDAP one would be nice, especially for LifeCluster?.
- A way to take one section from one backend and another section from another backend would be really nice.
- This now works, by separating functionality between UniConfGen and UniConf.
- There should be a NULL (no load/save) backend for temporary values in a
/tmptree, eg. for having things like "Public IPAddr" that get used in many places but shouldn't be saved. More temporary values will let us decouple more of the classes (eventually, hopefully removing pointers to the WvWeaver? class from almost all objects).- Done, and easily: the default UniConfGen is "null", and you can attach it to the tree root or any subtree.
- A multiple-files backend would be interesting: if it's a key
/foo/blah/weasels, why not store it in a fileweaselsin the directory/etc/foo/blah? Hmm...
- we definitely need a plaintext one (maybe even an old-WvConf? compatible one, ie. with sections named
- A smarter inheritence scheme: I want to define a user
apenwarrwhose settings are retrieved from a teamdevel(and so on, ifdevelis a sub-team of something else) unless they're overridden in theapenwarrsection. I want to be able to have some users be local, and some get inherited from the LifeCluster?. I want to be able to store the whole mess in the LdapServer? if I want, in different subsections (eg. have a /machines/mai/users/apenwarr and a /machines/mars/users/apenwarr and a /local/users/apenwarr; but if I ask for /users/apenwarr, it gives me the combination of them).- Currently works, using the
defaults(UniConfInheritance?) feature. Also, you can currently only define one default tree for any given tree, although the default tree can also have a default tree defined, ad infinitum. I'm wondering whether it would be more useful to have one tree (the "main" tree that everyone uses) with multiple levels of defaults, and then keep the "source" trees (LDAP, configfile 1, configfile 2, etc) without defaults at all. Not sure yet, but I suspect the current implementation might be the right one.
- Currently works, using the
- Backwards compatibility: Weaver? is too big to change all the uses of WvConf? at once. So we still need to support the old-style one-level
cfg.get("Section", "Entry", "Default")stuff for many different sections. We can do this by using a special backend for the/old-styletree, where the old-style requests just try to get/old-style/section/entryand the special backend parses those requests and acts like a symlink into the new-style sections. Also, UniConfEmu? provided a WvConf?-like API to a UniConf branch. - String-parseable: in case it's not obvious from the above, all keys should be representable like Unix paths:
/foo/blah/weaselsshould be a sectionweaselsin sectionblahwhich is in sectionfoo. I don't care if this restricts our namespace. That's just life, and life requires convenience :)- This definitely works, though if we're clever we can make it so keys can contain slashes: just backslash-escape them (or reuse the encoding from TclStyleLists).
- pphaneuf's comment reminded me that the API should support lists (arrays). I'm not sure how best to do that. Things like the
Groupsection (groupname = list of members) would be really handy if the lists auto-split themselves and entries could contain spaces.- I still have no good plan for this, though maybe just storing TclStyleLists as node values will do what we need.
- Defaults: I want default values to be able to exist without specifying them every time I do a get(). The infamous third argument to get() to specify a default has been useful, but it can be very tricky to change a default if we retrieve the same default from several different places. maybe_set() sort of fixes that for global options, but (say) for per-user options, where new users might be created at any time, it's not much good. I want something that lets us say globally that the default for "/users/*/allow pptp" is "no." Hmm, maybe the inheritence stuff will solve this problem more neatly, though.
- Done, again using the
defaults(UniConfInheritance?) feature.
- Done, again using the
- Schemas: I think it would be nice if we could specify the layout of a C++ struct and have UniConf parse a config section straight into that. (...) Nah, screw it.
ppatters (2002/02/20): Hmmm... I like the .save() idea - what about doing something to have it dump optionally to LDIF, or "old-style" config. (cfg["users"].save("/tmp/users.ldif",true) for LDIF (if false, then it would do old-style)... you could also have a .load() function to import from a file (I'm thinking conversion between Microsoft AD and LifeCluster? for instance - where you do a dump of the AD to LDIF, and import it into LifeCluster?). - I know this is a rev. 2 item, but it would be nice.
- apenwarr (2002/02/21): I don't see a problem with having an LDIF output format, but not as part of save() - we can make it save_ldif() or something. This would be particularly interesting since you could use it as a trivial way to import/export data from LDAP servers as well as just accessing config objects.
- pphaneuf (2002/02/21): You could steal a page from OpenStep? (yeah, that again!) and have the representation being done by a separate object. For example in OpenStep?, there are NSImageRep? descendents that can give you an NSImage from their data or turn an NSImage into data. Back-ends would be representations, and LDIF would be just another one.
pphaneuf (2002/02/20): Yeah, I think libPropList? could be used as a backend, if you kick it around a bit (array items have no name to use in an Unix path equivalent per se, but you could simply use the index number). I think it can do pretty much all of what is required, as a backend (some of the features are front-end related). An example of an hypothetical full WvPrint configuration in libPropList? format:
{
SpoolDir = /var/spool/wvprint;
Queues = {
lp = {
type = lpd;
host = echo;
queue = lp;
};
fax = {
type = fax;
modems = (
/dev/ttyS0;
/dev/ttyS1;
);
outgoingnumber = "+1 514 555 1234";
otheroption = "This setting";
};
};
};
Of course, the whole thing is a valid subsection as well, so you could have WvPrint = <what I put in the example> in the Weaver? configuration.
- pphaneuf (2002/02/21): Hmm, this really looks a lot like Perl, a few details aside.
apenwarr (2002/04/30): Thinking more about UniConfFileTree? this morning gave me the inspiration for ProjectUnity.
pphaneuf (2002/09/18): I'm sure you'll get a great following if UniConf could be used as a frontend for the WindowsRegistry?... If you'd be able to set a DWORD registry value without reminding it that a DWORD is still 4 bytes, or set an "ASCII zero-terminated string" without having to do an
strlen() ourself and tell it the actual length... :-)
- apenwarr (2002/09/24): That would be extremely cool, yes, and probably not even very hard. Also interesting would be the ability to parse/build/edit WindowsRegistry? files offline (eg. RoamingProfiles? stored on a Weaver?) so we could merge config changes into people's existing settings. The WinE? project has some code that can sort of deal with this.
dgtaylor? (2002/09/23): Just curious if anyone has run the conftest for uniconf... and if so if the following behaviour is correct:
for the IniFile? test, there is a section as follows:
[big]
fat/bob = 1
yet in the output, nothing involving big/fat/bob is ever output... is this desired behaviour for the cfg.dump?
The same thing happens later on with a [chicken] section
apenwarr (2002/09/24): This doesn't really happen to me; I just checked in a change to make it not overwrite test.ini, though, which might be what was confusing you. Note that that section was only being added by
conftest itself; it wasn't in the original test data. That key does appear for me in the dump that comes after the "changing some data" message.