summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/leap/base/config.py42
-rw-r--r--src/leap/base/providers.py2
-rw-r--r--src/leap/base/tests/test_providers.py2
-rw-r--r--src/leap/eip/checks.py76
-rw-r--r--src/leap/eip/config.py14
-rw-r--r--src/leap/eip/specs.py29
-rw-r--r--src/leap/eip/tests/data.py8
-rw-r--r--src/leap/eip/tests/test_checks.py9
8 files changed, 109 insertions, 73 deletions
diff --git a/src/leap/base/config.py b/src/leap/base/config.py
index 45a5f08a..7a65474a 100644
--- a/src/leap/base/config.py
+++ b/src/leap/base/config.py
@@ -6,12 +6,14 @@ import json
import logging
import requests
import socket
+import tempfile
import os
logger = logging.getLogger(name=__name__)
logger.setLevel('DEBUG')
import configuration
+import requests
from leap.base import exceptions
from leap.base import constants
@@ -55,6 +57,11 @@ class MetaConfigWithSpec(type):
# XXX in the near future, this is the
# place where we want to enforce
# singletons, read-only and stuff.
+
+ # TODO:
+ # - add a error handler for missing options that
+ # we can act easily upon (sys.exit is ugly, for $deity's sake)
+
def __new__(meta, classname, bases, classDict):
spec_options = classDict.get('spec', None)
# XXX if not spec_options, raise BadConfiguration or something
@@ -102,6 +109,7 @@ class JSONLeapConfig(BaseLeapConfig):
self._config = self.spec()
self._config.parse_args(list(args))
+ self.fetcher = kwargs.pop('fetcher', requests)
# mandatory baseconfig interface
@@ -111,7 +119,7 @@ class JSONLeapConfig(BaseLeapConfig):
folder, filename = os.path.split(to)
if folder and not os.path.isdir(folder):
mkdir_p(folder)
- # lazy evaluation until first level nest
+ # lazy evaluation until first level of nesting
# to allow lambdas with context-dependant info
# like os.path.expanduser
config = self.get_config()
@@ -120,14 +128,27 @@ class JSONLeapConfig(BaseLeapConfig):
config[k] = v()
self._config.serialize(to)
- def load(self, fromfile=None):
- # load should get a much more generic
- # argument. it could be, f.i., from_uri,
- # and call to Fetcher
-
+ def load(self, fromfile=None, from_uri=None, fetcher=None):
+ if from_uri is not None:
+ fetched = self.fetch(from_uri, fetcher=fetcher)
+ if fetched:
+ return
if fromfile is None:
fromfile = self.filename
- self._config.config = self._config.deserialize(fromfile)
+ newconfig = self._config.deserialize(fromfile)
+ # XXX check for no errors, etc
+ self._config.config = newconfig
+
+ def fetch(self, uri, fetcher=None):
+ if not fetcher:
+ fetcher = self.fetcher
+ request = fetcher.get(uri)
+ request.raise_for_status()
+ fd, fname = tempfile.mkstemp(suffix=".json")
+ with open(fname, 'w') as tmp:
+ tmp.write(json.dumps(request.json))
+ self._loadtemp(fname)
+ return True
def get_config(self):
return self._config.config
@@ -141,6 +162,12 @@ class JSONLeapConfig(BaseLeapConfig):
def filename(self):
return self.get_filename()
+ # private
+
+ def _loadtemp(self, filename):
+ self.load(fromfile=filename)
+ os.remove(filename)
+
def _slug_to_filename(self):
# is this going to work in winland if slug is "foo/bar" ?
folder, filename = os.path.split(self.slug)
@@ -157,6 +184,7 @@ class JSONLeapConfig(BaseLeapConfig):
#
# (might be moved to some class as we see fit, but
# let's remain functional for a while)
+# maybe base.config.util ??
#
diff --git a/src/leap/base/providers.py b/src/leap/base/providers.py
index 677dd6ec..ce30d4a4 100644
--- a/src/leap/base/providers.py
+++ b/src/leap/base/providers.py
@@ -9,7 +9,7 @@ class LeapProviderDefinition(baseconfig.JSONLeapConfig):
def _get_slug(self):
provider_path = baseconfig.get_default_provider_path()
return baseconfig.get_config_file(
- 'definition.json',
+ 'provider-definition.json',
folder=provider_path)
def _set_slug(self, *args, **kwargs):
diff --git a/src/leap/base/tests/test_providers.py b/src/leap/base/tests/test_providers.py
index 4920be93..23f63a95 100644
--- a/src/leap/base/tests/test_providers.py
+++ b/src/leap/base/tests/test_providers.py
@@ -46,7 +46,7 @@ class TestLeapProviderDefinition(BaseLeapTest):
self.home,
'.config', 'leap', 'providers',
'testprovider.example.org',
- 'definition.json'))
+ 'provider-definition.json'))
with self.assertRaises(AttributeError):
self.definition.slug = 23
diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py
index 4b2326a5..b57977f0 100644
--- a/src/leap/eip/checks.py
+++ b/src/leap/eip/checks.py
@@ -8,12 +8,11 @@ logger.setLevel(logging.DEBUG)
import requests
-from leap.base import config as baseconfig
from leap.base import constants as baseconstants
+from leap.base import providers
from leap.eip import config as eipconfig
from leap.eip import constants as eipconstants
from leap.eip import exceptions as eipexceptions
-from leap.util.fileutil import mkdir_p
"""
EIPConfigChecker
@@ -49,10 +48,11 @@ class EIPConfigChecker(object):
# argument on init.
# we want tests
# to be explicitely run.
- self.config = None
self.fetcher = fetcher
self.eipconfig = eipconfig.EIPConfig()
+ self.defaultprovider = providers.LeapProviderDefinition()
+ self.eipserviceconfig = eipconfig.EIPServiceConfig()
def run_all(self, checker=None, skip_download=False):
"""
@@ -74,7 +74,7 @@ class EIPConfigChecker(object):
checker.check_is_there_default_provider()
checker.fetch_definition(skip_download=skip_download)
- checker.fetch_eip_config(skip_download=skip_download)
+ checker.fetch_eip_service_config(skip_download=skip_download)
checker.check_complete_eip_config()
#checker.ping_gateway()
@@ -109,8 +109,7 @@ class EIPConfigChecker(object):
provider = config.get('provider', None)
if provider is None:
raise eipexceptions.EIPMissingDefaultProvider
- if config:
- self.config = config
+ # XXX raise also if malformed ProviderDefinition?
return True
def fetch_definition(self, skip_download=False,
@@ -120,65 +119,38 @@ class EIPConfigChecker(object):
"""
# TODO:
# - Implement diff
- # - overwrite if different.
+ # - overwrite only if different.
+ # (attend to serial field different, for instance)
+
logger.debug('fetching definition')
if skip_download:
logger.debug('(fetching def skipped)')
return True
if config is None:
- config = self.config
+ config = self.defaultprovider.get_config()
if uri is None:
- if config:
- domain = config.get('provider', None)
- else:
- domain = None
- uri = self._get_provider_definition_uri(
- domain=domain)
-
- # XXX move to JSONConfig Fetcher
- request = self.fetcher.get(uri)
- request.raise_for_status()
-
- definition_file = os.path.join(
- baseconfig.get_default_provider_path(),
- baseconstants.DEFINITION_EXPECTED_PATH)
-
- folder, filename = os.path.split(definition_file)
- if not os.path.isdir(folder):
- mkdir_p(folder)
- with open(definition_file, 'wb') as f:
- f.write(json.dumps(request.json, indent=4))
-
- def fetch_eip_config(self, skip_download=False,
- config=None, uri=None):
+ domain = config.get('provider', None)
+ uri = self._get_provider_definition_uri(domain=domain)
+
+ self.defaultprovider.load(from_uri=uri, fetcher=self.fetcher)
+ self.defaultprovider.save()
+
+ def fetch_eip_service_config(self, skip_download=False,
+ config=None, uri=None):
if skip_download:
return True
if config is None:
- config = self.config
+ config = self.eipserviceconfig.get_config()
if uri is None:
- if config:
- domain = config.get('provider', None)
- else:
- domain = None
- uri = self._get_eip_service_uri(
- domain=domain)
-
- # XXX move to JSONConfig Fetcher
- request = self.fetcher.get(uri)
- request.raise_for_status()
-
- definition_file = os.path.join(
- baseconfig.get_default_provider_path(),
- eipconstants.EIP_SERVICE_EXPECTED_PATH)
-
- folder, filename = os.path.split(definition_file)
- if not os.path.isdir(folder):
- mkdir_p(folder)
- with open(definition_file, 'wb') as f:
- f.write(json.dumps(request.json, indent=4))
+ domain = config.get('provider', None)
+ uri = self._get_eip_service_uri(domain=domain)
+
+ self.eipserviceconfig.load(from_uri=uri, fetcher=self.fetcher)
+ self.eipserviceconfig.save()
def check_complete_eip_config(self, config=None):
+ # TODO check for gateway
if config is None:
config = self.config
try:
diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py
index a7b24f9b..b6c38a77 100644
--- a/src/leap/eip/config.py
+++ b/src/leap/eip/config.py
@@ -49,6 +49,20 @@ class EIPConfig(baseconfig.JSONLeapConfig):
slug = property(_get_slug, _set_slug)
+class EIPServiceConfig(baseconfig.JSONLeapConfig):
+ spec = eipspecs.eipservice_config_spec
+
+ def _get_slug(self):
+ return baseconfig.get_config_file(
+ 'eip-service.json',
+ folder=baseconfig.get_default_provider_path())
+
+ def _set_slug(self):
+ raise AttributeError("you cannot set slug")
+
+ slug = property(_get_slug, _set_slug)
+
+
def check_or_create_default_vpnconf(config):
"""
checks that a vpn config file
diff --git a/src/leap/eip/specs.py b/src/leap/eip/specs.py
index a39e5979..e617574c 100644
--- a/src/leap/eip/specs.py
+++ b/src/leap/eip/specs.py
@@ -64,3 +64,32 @@ eipconfig_spec = {
'type': unicode
}
}
+
+eipservice_config_spec = {
+ 'serial': {
+ 'type': int,
+ 'required': True,
+ 'default': 1
+ },
+ 'version': {
+ 'type': unicode,
+ 'required': True,
+ 'default': "0.1.0"
+ },
+ 'capabilities': {
+ 'type': dict,
+ 'default': {
+ "transport": ["openvpn"],
+ "ports": ["80", "53"],
+ "protocols": ["udp", "tcp"],
+ "static_ips": True,
+ "adblock": True}
+ },
+ 'gateways': {
+ 'type': list,
+ 'default': [{"country_code": "us",
+ "label": {"en":"west"},
+ "capabilities": {},
+ "hosts": ["1.2.3.4", "1.2.3.5"]}]
+ }
+}
diff --git a/src/leap/eip/tests/data.py b/src/leap/eip/tests/data.py
index 9067c270..284b398f 100644
--- a/src/leap/eip/tests/data.py
+++ b/src/leap/eip/tests/data.py
@@ -38,13 +38,5 @@ EIP_SAMPLE_SERVICE = {
"label": {"en":"west"},
"capabilities": {},
"hosts": ["1.2.3.4", "1.2.3.5"]},
- {"country_code": "us",
- "label": {"en":"east"},
- "capabilities": {},
- "hosts": ["1.2.3.4", "1.2.3.5"]},
- {"country_code": "fr",
- "label": {},
- "capabilities": {},
- "hosts": ["1.2.3.4", "1.2.3.5"]}
]
}
diff --git a/src/leap/eip/tests/test_checks.py b/src/leap/eip/tests/test_checks.py
index 5697ad10..1e629203 100644
--- a/src/leap/eip/tests/test_checks.py
+++ b/src/leap/eip/tests/test_checks.py
@@ -40,7 +40,8 @@ class EIPCheckTest(BaseLeapTest):
self.assertTrue(hasattr(checker, "check_is_there_default_provider"),
"missing meth")
self.assertTrue(hasattr(checker, "fetch_definition"), "missing meth")
- self.assertTrue(hasattr(checker, "fetch_eip_config"), "missing meth")
+ self.assertTrue(hasattr(checker, "fetch_eip_service_config"),
+ "missing meth")
self.assertTrue(hasattr(checker, "check_complete_eip_config"),
"missing meth")
self.assertTrue(hasattr(checker, "ping_gateway"), "missing meth")
@@ -55,7 +56,7 @@ class EIPCheckTest(BaseLeapTest):
"not called")
self.assertTrue(mc.fetch_definition.called,
"not called")
- self.assertTrue(mc.fetch_eip_config.called,
+ self.assertTrue(mc.fetch_eip_service_config.called,
"not called")
self.assertTrue(mc.check_complete_eip_config.called,
"not called")
@@ -133,13 +134,13 @@ class EIPCheckTest(BaseLeapTest):
# (and proper EIPExceptions are raised).
# Look at base.test_config.
- def test_fetch_eip_config(self):
+ def test_fetch_eip_service_config(self):
with patch.object(requests, "get") as mocked_get:
mocked_get.return_value.status_code = 200
mocked_get.return_value.json = testdata.EIP_SAMPLE_SERVICE
checker = eipchecks.EIPConfigChecker(fetcher=requests)
sampleconfig = testdata.EIP_SAMPLE_JSON
- checker.fetch_definition(config=sampleconfig)
+ checker.fetch_eip_service_config(config=sampleconfig)
def test_check_complete_eip_config(self):
checker = eipchecks.EIPConfigChecker()