mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-10 20:30:00 +00:00
Check for unknown config options
The list of valid sections + config-items came from grep'ing the source for `.get_config`
This commit is contained in:
parent
00ea41ef2c
commit
2732c37941
@ -17,7 +17,7 @@ from allmydata.immutable.offloaded import Helper
|
||||
from allmydata.control import ControlServer
|
||||
from allmydata.introducer.client import IntroducerClient
|
||||
from allmydata.util import (hashutil, base32, pollmixin, log, keyutil, idlib,
|
||||
yamlutil)
|
||||
yamlutil, configutil)
|
||||
from allmydata.util.encodingutil import (get_filesystem_encoding,
|
||||
from_utf8_or_none)
|
||||
from allmydata.util.fileutil import abspath_expanduser_unicode
|
||||
@ -28,7 +28,7 @@ from allmydata.history import History
|
||||
from allmydata.interfaces import IStatsProducer, SDMF_VERSION, MDMF_VERSION
|
||||
from allmydata.nodemaker import NodeMaker
|
||||
from allmydata.blacklist import Blacklist
|
||||
from allmydata.node import OldConfigOptionError
|
||||
from allmydata.node import OldConfigOptionError, _common_config_sections
|
||||
|
||||
|
||||
KiB=1024
|
||||
@ -37,6 +37,62 @@ GiB=1024*MiB
|
||||
TiB=1024*GiB
|
||||
PiB=1024*TiB
|
||||
|
||||
def _valid_config_sections():
|
||||
cfg = _common_config_sections()
|
||||
cfg.update({
|
||||
"client": (
|
||||
"helper.furl",
|
||||
"introducer.furl",
|
||||
"key_generator.furl",
|
||||
"mutable.format",
|
||||
"peers.preferred",
|
||||
"shares.happy",
|
||||
"shares.needed",
|
||||
"shares.total",
|
||||
"stats_gatherer.furl",
|
||||
),
|
||||
"drop_upload": ( # deprecated already?
|
||||
"enabled",
|
||||
),
|
||||
"ftpd": (
|
||||
"accounts.file",
|
||||
"accounts.url",
|
||||
"enabled",
|
||||
"port",
|
||||
),
|
||||
"storage": (
|
||||
"debug_discard",
|
||||
"enabled",
|
||||
"expire.cutoff_date",
|
||||
"expire.enabled",
|
||||
"expire.immutable",
|
||||
"expire.mode",
|
||||
"expire.mode",
|
||||
"expire.mutable",
|
||||
"expire.override_lease_duration",
|
||||
"readonly",
|
||||
"reserved_space",
|
||||
),
|
||||
"sftpd": (
|
||||
"accounts.file",
|
||||
"accounts.url",
|
||||
"enabled",
|
||||
"host_privkey_file",
|
||||
"host_pubkey_file",
|
||||
"port",
|
||||
),
|
||||
"helper": (
|
||||
"enabled",
|
||||
),
|
||||
"magic_folder": (
|
||||
"download.umask",
|
||||
"enabled",
|
||||
"local.directory",
|
||||
),
|
||||
})
|
||||
return cfg
|
||||
|
||||
|
||||
def _make_secret():
|
||||
return base32.b2a(os.urandom(hashutil.CRYPTO_VAL_SIZE)) + "\n"
|
||||
|
||||
@ -123,6 +179,7 @@ class Client(node.Node, pollmixin.PollMixin):
|
||||
node.Node.__init__(self, basedir)
|
||||
# All tub.registerReference must happen *after* we upcall, since
|
||||
# that's what does tub.setLocation()
|
||||
configutil.validate_config(self.config_fname, self.config, _valid_config_sections())
|
||||
self._magic_folder = None
|
||||
self.started_timestamp = time.time()
|
||||
self.logSource="Client"
|
||||
|
@ -5,13 +5,17 @@ from twisted.application import service
|
||||
from foolscap.api import Referenceable
|
||||
import allmydata
|
||||
from allmydata import node
|
||||
from allmydata.util import log, rrefutil
|
||||
from allmydata.util import log, rrefutil, configutil
|
||||
from allmydata.util.fileutil import abspath_expanduser_unicode
|
||||
from allmydata.introducer.interfaces import \
|
||||
RIIntroducerPublisherAndSubscriberService_v2
|
||||
from allmydata.introducer.common import unsign_from_foolscap, \
|
||||
SubscriberDescriptor, AnnouncementDescriptor
|
||||
|
||||
def _valid_config_sections():
|
||||
return node._common_config_sections()
|
||||
|
||||
|
||||
class FurlFileConflictError(Exception):
|
||||
pass
|
||||
|
||||
@ -22,7 +26,7 @@ class IntroducerNode(node.Node):
|
||||
|
||||
def __init__(self, basedir=u"."):
|
||||
node.Node.__init__(self, basedir)
|
||||
self.read_config()
|
||||
configutil.validate_config(self.config_fname, self.config, _valid_config_sections())
|
||||
self.init_introducer()
|
||||
webport = self.get_config("node", "web.port", None)
|
||||
if webport:
|
||||
|
@ -29,6 +29,39 @@ def _import_i2p():
|
||||
except ImportError: # pragma: no cover
|
||||
return None
|
||||
|
||||
def _common_config_sections():
|
||||
return {
|
||||
"connections": (
|
||||
"tcp",
|
||||
),
|
||||
"node": (
|
||||
"log_gatherer.furl",
|
||||
"nickname",
|
||||
"reveal-ip-address",
|
||||
"tempdir",
|
||||
"timeout.disconnect",
|
||||
"timeout.keepalive",
|
||||
"tub.location",
|
||||
"tub.port",
|
||||
"web.port",
|
||||
"web.static",
|
||||
),
|
||||
"i2p": (
|
||||
"enabled",
|
||||
"i2p.configdir",
|
||||
"i2p.executable",
|
||||
"launch",
|
||||
"sam.port",
|
||||
),
|
||||
"tor": (
|
||||
"control.port",
|
||||
"enabled",
|
||||
"launch",
|
||||
"socks.port",
|
||||
"tor.executable",
|
||||
),
|
||||
}
|
||||
|
||||
# Add our application versions to the data that Foolscap's LogPublisher
|
||||
# reports.
|
||||
for thing, things_version in get_package_versions().iteritems():
|
||||
@ -91,6 +124,7 @@ class Node(service.MultiService):
|
||||
def __init__(self, basedir=u"."):
|
||||
service.MultiService.__init__(self)
|
||||
self.basedir = abspath_expanduser_unicode(unicode(basedir))
|
||||
self.config_fname = os.path.join(self.basedir, "tahoe.cfg")
|
||||
self._portnumfile = os.path.join(self.basedir, self.PORTNUMFILE)
|
||||
fileutil.make_dirs(os.path.join(self.basedir, "private"), 0700)
|
||||
open(os.path.join(self.basedir, "private", "README"), "w").write(PRIV_README)
|
||||
@ -159,11 +193,10 @@ class Node(service.MultiService):
|
||||
self.error_about_old_config_files()
|
||||
self.config = ConfigParser.SafeConfigParser()
|
||||
|
||||
tahoe_cfg = os.path.join(self.basedir, "tahoe.cfg")
|
||||
try:
|
||||
self.config = configutil.get_config(tahoe_cfg)
|
||||
self.config = configutil.get_config(self.config_fname)
|
||||
except EnvironmentError:
|
||||
if os.path.exists(tahoe_cfg):
|
||||
if os.path.exists(self.config_fname):
|
||||
raise
|
||||
|
||||
def error_about_old_config_files(self):
|
||||
|
@ -32,3 +32,45 @@ class ConfigUtilTests(CLITestMixin, GridTestMixin, unittest.TestCase):
|
||||
|
||||
config = configutil.get_config(tahoe_cfg)
|
||||
self.failUnlessEqual(config.get("node", "descriptor"), descriptor)
|
||||
|
||||
def test_config_validation_success(self):
|
||||
d = self.mktemp()
|
||||
os.mkdir(d)
|
||||
fname = os.path.join(d, 'tahoe.cfg')
|
||||
|
||||
with open(fname, 'w') as f:
|
||||
f.write('[node]\nvalid = foo\n')
|
||||
|
||||
config = configutil.get_config(fname)
|
||||
# should succeed, no exceptions
|
||||
configutil.validate_config(fname, config, dict(node=['valid']))
|
||||
|
||||
def test_config_validation_invalid_item(self):
|
||||
d = self.mktemp()
|
||||
os.mkdir(d)
|
||||
fname = os.path.join(d, 'tahoe.cfg')
|
||||
|
||||
with open(fname, 'w') as f:
|
||||
f.write('[node]\nvalid = foo\ninvalid = foo\n')
|
||||
|
||||
config = configutil.get_config(fname)
|
||||
self.assertRaises(
|
||||
configutil.UnknownConfigError,
|
||||
configutil.validate_config,
|
||||
fname, config, dict(node=['valid']),
|
||||
)
|
||||
|
||||
def test_config_validation_invalid_section(self):
|
||||
d = self.mktemp()
|
||||
os.mkdir(d)
|
||||
fname = os.path.join(d, 'tahoe.cfg')
|
||||
|
||||
with open(fname, 'w') as f:
|
||||
f.write('[node]\nvalid = foo\n[invalid]\n')
|
||||
|
||||
config = configutil.get_config(fname)
|
||||
self.assertRaises(
|
||||
configutil.UnknownConfigError,
|
||||
configutil.validate_config,
|
||||
fname, config, dict(node=['valid']),
|
||||
)
|
||||
|
@ -2,6 +2,14 @@
|
||||
from ConfigParser import SafeConfigParser
|
||||
|
||||
|
||||
class UnknownConfigError(Exception):
|
||||
"""
|
||||
An unknown config item was found.
|
||||
|
||||
This is possibly raised by validate_config()
|
||||
"""
|
||||
|
||||
|
||||
def get_config(tahoe_cfg):
|
||||
config = SafeConfigParser()
|
||||
f = open(tahoe_cfg, "rb")
|
||||
@ -27,3 +35,28 @@ def write_config(tahoe_cfg, config):
|
||||
config.write(f)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def validate_config(fname, cfg, valid_sections):
|
||||
"""
|
||||
raises UnknownConfigError if there are any unknown sections or config
|
||||
values.
|
||||
"""
|
||||
for section in cfg.sections():
|
||||
try:
|
||||
valid_in_section = valid_sections[section]
|
||||
except KeyError:
|
||||
raise UnknownConfigError(
|
||||
"'{fname}' contains unknown section [{section}]".format(
|
||||
fname=fname,
|
||||
section=section,
|
||||
)
|
||||
)
|
||||
for option in cfg.options(section):
|
||||
if option not in valid_in_section:
|
||||
raise UnknownConfigError(
|
||||
"'{fname}' section [{section}] contains unknown option '{option}'".format(
|
||||
fname=fname,
|
||||
section=section,
|
||||
option=option,
|
||||
)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user