Include resources from store when deploying (#102)
[osm/N2VC.git] / juju / model.py
index 0278ae6..c76ce88 100644 (file)
@@ -16,6 +16,7 @@ import yaml
 import theblues.charmstore
 import theblues.errors
 
+from . import tag
 from .client import client
 from .client import watcher
 from .client import connection
@@ -992,9 +993,7 @@ class Model(object):
 
         TODO::
 
-            - application_name is required; fill this in automatically if not
-              provided by caller
-            - series is required; how do we pick a default?
+            - support local resources
 
         """
         if storage:
@@ -1046,6 +1045,11 @@ class Model(object):
                 if not channel:
                     channel = 'stable'
                 await client_facade.AddCharm(channel, entity_id)
+                # XXX: we're dropping local resources here, but we don't
+                # actually support them yet anyway
+                resources = await self._add_store_resources(application_name,
+                                                            entity_id,
+                                                            entity)
             else:
                 # We have a local charm dir that needs to be uploaded
                 charm_dir = os.path.abspath(
@@ -1071,6 +1075,37 @@ class Model(object):
                 placement=parse_placement(to),
             )
 
+    async def _add_store_resources(self, application, entity_url, entity=None):
+        if not entity:
+            # avoid extra charm store call if one was already made
+            entity = await self.charmstore.entity(entity_url)
+        resources = [
+            {
+                'description': resource['Description'],
+                'fingerprint': resource['Fingerprint'],
+                'name': resource['Name'],
+                'path': resource['Path'],
+                'revision': resource['Revision'],
+                'size': resource['Size'],
+                'type_': resource['Type'],
+                'origin': 'store',
+            } for resource in entity['Meta']['resources']
+        ]
+
+        if not resources:
+            return None
+
+        resources_facade = client.ResourcesFacade()
+        resources_facade.connect(self.connection)
+        response = await resources_facade.AddPendingResources(
+            tag.application(application),
+            entity_url,
+            [client.CharmResource(**resource) for resource in resources])
+        resource_map = {resource['name']: pid
+                        for resource, pid
+                        in zip(resources, response.pending_ids)}
+        return resource_map
+
     async def _deploy(self, charm_url, application, series, config,
                       constraints, endpoint_bindings, resources, storage,
                       channel=None, num_units=None, placement=None):
@@ -1707,6 +1742,11 @@ class BundleHandler(object):
         """
         # resolve indirect references
         charm = self.resolve(charm)
+        # the bundle plan doesn't actually do anything with resources, even
+        # though it ostensibly gives us something (None) for that param
+        if not charm.startswith('local:'):
+            resources = await self.model._add_store_resources(application,
+                                                              charm)
         await self.model._deploy(
             charm_url=charm,
             application=application,