launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #10777
[Merge] lp:~jtv/maas/store-worker-api-credentials into lp:maas
Jeroen T. Vermeulen has proposed merging lp:~jtv/maas/store-worker-api-credentials into lp:maas.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~jtv/maas/store-worker-api-credentials/+merge/118866
This builds on existing infrastructure for recording worker secrets. We may need to adapt that infrastructure to support multi-processing, but that is a largely isolated change.
Julian just told me the format in which credentials are passed (which I had completely forgotten) but the tuple representation is a direct fit to what we already have coded up in the API client.
Jeroen
--
https://code.launchpad.net/~jtv/maas/store-worker-api-credentials/+merge/118866
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jtv/maas/store-worker-api-credentials into lp:maas.
=== added file 'src/provisioningserver/auth.py'
--- src/provisioningserver/auth.py 1970-01-01 00:00:00 +0000
+++ src/provisioningserver/auth.py 2012-08-09 04:22:20 +0000
@@ -0,0 +1,46 @@
+# Copyright 2012 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""API credentials for node-group workers."""
+
+from __future__ import (
+ absolute_import,
+ print_function,
+ unicode_literals,
+ )
+
+__metaclass__ = type
+__all__ = [
+ 'get_recorded_api_credentials',
+ 'record_api_credentials',
+ ]
+
+# API credentials as last sent by the server. The worker uses these
+# credentials to access the MAAS API.
+# Shared between threads.
+recorded_api_credentials = None
+
+
+def record_api_credentials(api_credentials):
+ """Update the recorded API credentials.
+
+ :param api_credentials: Newly received API credentials, in the form of
+ a single string: consumer key, resource token, and resource seret
+ separated by colons.
+ """
+ global recorded_api_credentials
+ recorded_api_credentials = api_credentials
+
+
+def get_recorded_api_credentials():
+ """Return API credentials as last received from the server.
+
+ :return: If credentials have been received, a tuple of
+ (consumer_key, resource_token, resource_secret) as expected by
+ :class:`MAASOauth`. Otherwise, None.
+ """
+ credentials_string = recorded_api_credentials
+ if credentials_string is None:
+ return None
+ else:
+ return tuple(credentials_string.split(':'))
=== modified file 'src/provisioningserver/tasks.py'
--- src/provisioningserver/tasks.py 2012-08-08 11:04:45 +0000
+++ src/provisioningserver/tasks.py 2012-08-09 04:22:20 +0000
@@ -29,6 +29,7 @@
from celery.task import task
from celeryconfig import DHCP_CONFIG_FILE
+from provisioningserver.auth import record_api_credentials
from provisioningserver.dhcp import (
config,
leases,
@@ -47,6 +48,7 @@
# For each item passed to refresh_secrets, a refresh function to give it to.
refresh_functions = {
+ 'api_credentials': record_api_credentials,
'omapi_shared_key': leases.record_omapi_shared_key,
}
=== added file 'src/provisioningserver/tests/test_auth.py'
--- src/provisioningserver/tests/test_auth.py 1970-01-01 00:00:00 +0000
+++ src/provisioningserver/tests/test_auth.py 2012-08-09 04:22:20 +0000
@@ -0,0 +1,48 @@
+# Copyright 2012 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests for management of node-group workers' API credentials."""
+
+from __future__ import (
+ absolute_import,
+ print_function,
+ unicode_literals,
+ )
+
+__metaclass__ = type
+__all__ = []
+
+from maastesting.factory import factory
+from maastesting.testcase import TestCase
+from provisioningserver import auth
+
+
+def make_credentials():
+ """Produce a tuple of API credentials."""
+ return (
+ factory.make_name('consumer-key'),
+ factory.make_name('resource-token'),
+ factory.make_name('resource-secret'),
+ )
+
+
+def represent_credentials(credentials):
+ """Represent a tuple of API credentials as a credentials string."""
+ return ':'.join(credentials)
+
+
+class TestAuth(TestCase):
+
+ def test_record_api_credentials_records_credentials_string(self):
+ creds_string = represent_credentials(make_credentials())
+ auth.record_api_credentials(creds_string)
+ self.assertEqual(creds_string, auth.recorded_api_credentials)
+
+ def test_get_recorded_api_credentials_returns_credentials_as_tuple(self):
+ creds = make_credentials()
+ auth.record_api_credentials(represent_credentials(creds))
+ self.assertEqual(creds, auth.get_recorded_api_credentials())
+
+ def test_get_recorded_api_credentials_returns_None_without_creds(self):
+ auth.record_api_credentials(None)
+ self.assertIsNone(auth.get_recorded_api_credentials())
=== modified file 'src/provisioningserver/tests/test_tasks.py'
--- src/provisioningserver/tests/test_tasks.py 2012-08-08 05:54:08 +0000
+++ src/provisioningserver/tests/test_tasks.py 2012-08-09 04:22:20 +0000
@@ -23,6 +23,7 @@
from maastesting.testcase import TestCase
from netaddr import IPNetwork
from provisioningserver import tasks
+from provisioningserver.auth import get_recorded_api_credentials
from provisioningserver.dhcp import leases
from provisioningserver.dns.config import (
conf,
@@ -96,15 +97,24 @@
def test_breaks_on_unknown_item(self):
self.assertRaises(AssertionError, refresh_secrets, not_an_item=None)
+ def test_works_as_a_task(self):
+ self.assertTrue(refresh_secrets.delay().successful())
+
+ def test_updates_api_credentials(self):
+ credentials = (
+ factory.make_name('key'),
+ factory.make_name('token'),
+ factory.make_name('secret'),
+ )
+ refresh_secrets(api_credentials=':'.join(credentials))
+ self.assertEqual(credentials, get_recorded_api_credentials())
+
def test_updates_omapi_shared_key(self):
self.patch(leases, 'recorded_omapi_shared_key', None)
key = factory.make_name('omapi-shared-key')
refresh_secrets(omapi_shared_key=key)
self.assertEqual(key, leases.recorded_omapi_shared_key)
- def test_works_as_a_task(self):
- self.assertTrue(refresh_secrets.delay().successful())
-
class TestPowerTasks(TestCase):