← Back to team overview

cf-charmers team mailing list archive

[Merge] lp:~johnsca/charms/trusty/cloudfoundry/charmstore into lp:~cf-charmers/charms/trusty/cloudfoundry/trunk

 

Cory Johns has proposed merging lp:~johnsca/charms/trusty/cloudfoundry/charmstore into lp:~cf-charmers/charms/trusty/cloudfoundry/trunk.

Requested reviews:
  Cloud Foundry Charmers (cf-charmers)

For more details, see:
https://code.launchpad.net/~johnsca/charms/trusty/cloudfoundry/charmstore/+merge/236399

Changes to deploy from charm store, which is the default.  I also have the charms pushed to my namespace (https://code.launchpad.net/~johnsca) and will push them to ~cf-charmers if this looks good.
-- 
https://code.launchpad.net/~johnsca/charms/trusty/cloudfoundry/charmstore/+merge/236399
Your team Cloud Foundry Charmers is requested to review the proposed merge of lp:~johnsca/charms/trusty/cloudfoundry/charmstore into lp:~cf-charmers/charms/trusty/cloudfoundry/trunk.
=== modified file 'charmgen/generator.py'
--- charmgen/generator.py	2014-09-18 19:37:22 +0000
+++ charmgen/generator.py	2014-09-29 18:10:35 +0000
@@ -21,11 +21,13 @@
 class CharmGenerator(object):
     author = "CloudFoundry Charm Generator <cs:~cf-charmers/cloudfoundry>"
 
-    def __init__(self, releases, service_registry):
+    def __init__(self, releases, service_registry, from_charmstore=True, cs_namespace='~cf-charmers'):
         self.__releases = releases
         self.release = None
         self.release_version = None
         self.service_registry = service_registry
+        self.from_charmstore = from_charmstore
+        self.cs_namespace = cs_namespace
 
     def select_release(self, version):
         if isinstance(version, basestring):
@@ -126,10 +128,14 @@
         if charm_id.startswith('cs:'):
             return dict(charm=charm_id)
         else:
-            return dict(
-                charm=charm_id,
-                branch="local:trusty/{}".format(charm_id)
-            )
+            if self.from_charmstore:
+                namespace = '{}/'.format(self.cs_namespace) if self.cs_namespace else ''
+                return {"charm": "cs:{}trusty/{}".format(namespace, charm_id)}
+            else:
+                return {
+                    "charm": charm_id,
+                    "branch": "local:trusty/{}".format(charm_id)
+                }
 
     def _parse_charm_ref(self, service_id):
         if isinstance(service_id, tuple):
@@ -277,22 +283,23 @@
             os.makedirs(repo)
         self.generate_deployment(target_dir, placement)
 
-        for _, charm_name, _ in self._get_managed_charms():
-            charm_path = os.path.join(repo, charm_name)
-            if not os.path.exists(charm_path):
-                os.makedirs(charm_path)
+        if not self.from_charmstore:
+            for _, charm_name, _ in self._get_managed_charms():
+                charm_path = os.path.join(repo, charm_name)
+                if not os.path.exists(charm_path):
+                    os.makedirs(charm_path)
 
-            self.generate_charm(charm_name, charm_path)
-            shutil.copytree(pkg_resources.resource_filename(
-                __name__, '../cloudfoundry'),
-                os.path.join(charm_path, 'hooks', 'cloudfoundry'))
-            shutil.copytree(pkg_resources.resource_filename(
-                __name__, '../files'),
-                os.path.join(charm_path, 'files'))
-            # copy charmhelpers into the hook_dir
-            shutil.copytree(pkg_resources.resource_filename(
-                __name__, '../hooks/charmhelpers'),
-                os.path.join(charm_path, 'hooks', 'charmhelpers'))
+                self.generate_charm(charm_name, charm_path)
+                shutil.copytree(pkg_resources.resource_filename(
+                    __name__, '../cloudfoundry'),
+                    os.path.join(charm_path, 'hooks', 'cloudfoundry'))
+                shutil.copytree(pkg_resources.resource_filename(
+                    __name__, '../files'),
+                    os.path.join(charm_path, 'files'))
+                # copy charmhelpers into the hook_dir
+                shutil.copytree(pkg_resources.resource_filename(
+                    __name__, '../hooks/charmhelpers'),
+                    os.path.join(charm_path, 'hooks', 'charmhelpers'))
 
 
 def main(args=None):
@@ -320,7 +327,7 @@
             raise SystemExit("Release already generated: {}".format(
                 options.directory))
 
-    g = CharmGenerator(RELEASES, SERVICES)
+    g = CharmGenerator(RELEASES, SERVICES, from_charmstore=False)
     g.select_release(options.release)
     placement = g.load_placement_policy(options.placement, options.placements_file)
     g.generate(options.directory, placement)

=== modified file 'config.yaml'
--- config.yaml	2014-09-18 19:37:22 +0000
+++ config.yaml	2014-09-29 18:10:35 +0000
@@ -46,3 +46,19 @@
             This can reduce the number of requests to the upstream artifacts
             repository, but at the cost of significantly increasing the
             storage requirements on the deployed orchestrator charm.
+    charmstore_namespace:
+        type: string
+        default: ~cf-charmers
+        description: >
+            The namespace in the charmstore from which to install the
+            dependent charms for the individual Cloud Foundry components.
+            Set to an empty string to only install Recommended charms (may
+            not be as up to date as the default ~cf-charmers namespace).
+    generate_dependents:
+        type: boolean
+        default: false
+        description: >
+            Generate the dependent charms for the individual Cloud Foundry
+            components on demand, instead of installing from the charm store.
+            This option is intended only for testing and development purposes,
+            and is not recommended for normal usage.

=== modified file 'hooks/common.py'
--- hooks/common.py	2014-09-18 19:37:22 +0000
+++ hooks/common.py	2014-09-29 18:10:35 +0000
@@ -47,12 +47,14 @@
 def generate(s):
     config = hookenv.config()
     version = config.get('cf_version')
+    from_charmstore = not config['generate_dependents']
+    cs_namespace = config['charmstore_namespace']
     if not version or version == 'latest':
         version = RELEASES[0]['releases'][1]
     build_dir = os.path.join(hookenv.charm_dir(), 'build', str(version))
     if os.path.exists(build_dir):
         shutil.rmtree(build_dir)
-    generator = CharmGenerator(RELEASES, SERVICES)
+    generator = CharmGenerator(RELEASES, SERVICES, from_charmstore, cs_namespace)
     generator.select_release(version)
     placement = generator.load_placement_policy(config['placement'])
     generator.generate(build_dir, placement)
@@ -97,9 +99,9 @@
         # the generated charms; this can't be done in the bundle because
         # the orchestrator is not defined in the bundle
         orchestrator = hookenv.service_name()
-        for service_name, service_data in bundle['cloudfoundry']['services'].items():
-            # XXX: explicitly check if service has orchestrator interface
-            if not service_data['charm'].startswith('cs:'):
+        for service_name in bundle['cloudfoundry']['services'].keys():
+            charm = deployment.get_charm_for(service_name)
+            if 'orchestrator' in charm.metadata.get('requires', {}):
                 try:
                     env.add_relation(orchestrator, service_name)
                 except EnvError as e:

=== modified file 'tests/test_generator.py'
--- tests/test_generator.py	2014-09-18 19:37:22 +0000
+++ tests/test_generator.py	2014-09-29 18:10:35 +0000
@@ -129,14 +129,28 @@
             (('s1', 'nats'), ('s2', 'nats')),
         ])
 
-    def test_build_charm_ref(self):
-        g = CharmGenerator(RELEASES, SERVICES)
+    def test_build_charm_ref_local(self):
+        g = CharmGenerator(RELEASES, SERVICES, from_charmstore=False)
         self.assertEqual(g._build_charm_ref('cs:trusty/mysql'),
                          {'charm': 'cs:trusty/mysql'})
         self.assertEqual(g._build_charm_ref('cloud_controller_v1'),
                          {'charm': 'cloud_controller_v1',
                           'branch': 'local:trusty/cloud_controller_v1'})
 
+    def test_build_charm_ref_cs(self):
+        g = CharmGenerator(RELEASES, SERVICES, from_charmstore=True)
+        self.assertEqual(g._build_charm_ref('cs:trusty/mysql'),
+                         {'charm': 'cs:trusty/mysql'})
+        self.assertEqual(g._build_charm_ref('cloud_controller_v1'),
+                         {'charm': 'cs:~cf-charmers/trusty/cloud_controller_v1'})
+
+    def test_build_charm_ref_cs_recommended(self):
+        g = CharmGenerator(RELEASES, SERVICES, from_charmstore=True, cs_namespace='')
+        self.assertEqual(g._build_charm_ref('cs:trusty/mysql'),
+                         {'charm': 'cs:trusty/mysql'})
+        self.assertEqual(g._build_charm_ref('cloud_controller_v1'),
+                         {'charm': 'cs:trusty/cloud_controller_v1'})
+
     def test_parse_charm_ref(self):
         g = CharmGenerator(RELEASES, SERVICES)
         self.assertEqual(g._parse_charm_ref('cs:trusty/mysql'),
@@ -261,7 +275,7 @@
         })
 
     def test_build_deployment(self):
-        g = CharmGenerator(RELEASES, SERVICES)
+        g = CharmGenerator(RELEASES, SERVICES, from_charmstore=False)
         g.select_release(173)
         data = g.build_deployment(None)
         cf = data['cloudfoundry']
@@ -295,7 +309,7 @@
                 self.assertEqual(cf['series'], 'trusty')
 
     def test_generate(self):
-        g = CharmGenerator(RELEASES, SERVICES)
+        g = CharmGenerator(RELEASES, SERVICES, from_charmstore=False)
         g.select_release(173)
         with tempdir() as tmpdir:
             g.generate(tmpdir, None)


Follow ups