Merge lp:~ev/charms/xenial/cassandra/snap into lp:~cassandra-charmers/charms/xenial/cassandra/trunk

Proposed by Evan
Status: Merged
Merge reported by: Stuart Bishop
Merged at revision: not available
Proposed branch: lp:~ev/charms/xenial/cassandra/snap
Merge into: lp:~cassandra-charmers/charms/xenial/cassandra/trunk
Diff against target: 498 lines (+224/-31)
4 files modified
config.yaml (+4/-4)
hooks/actions.py (+10/-2)
hooks/helpers.py (+167/-24)
tests/test_helpers.py (+43/-1)
To merge this branch: bzr merge lp:~ev/charms/xenial/cassandra/snap
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Review via email: mp+297723@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Stuart Bishop (stub) wrote :

Comments inline.

Revision history for this message
Evan (ev) wrote :

Thanks for the thorough review! I've fixed the raised issues and mentioned the individual revnos inline.

Revision history for this message
Stuart Bishop (stub) wrote :

This is all looking good. A few comments inline, but nothing series except for the encrypt() method failing under trusty.

We will want integration tests, which starts with creating TestSnapDeployment(Test3UnitDeployment) in tests/test_integration.py. The tests and harness on this branch are Juju1 specific (I can sort Juju 2.0 mostly by syncing testing/amuletfixture.py to the PostgreSQL charm's version).

The integration tests at the moment will almost certainly fail for snap, as they 'juju run --unit ... nodetool ...' so we either need the charm to create symlinks in /usr/local/bin so the standard tool names work, or update the callsites in the test suite (just 3 or 4 I see). Ideally the snap would use the standard tool names like 'nodetool' rather than 'cassandra.nodetool', but from what I can tell that would mean maintaining a separate snap for each cli tool?

Revision history for this message
Evan (ev) :
lp:~ev/charms/xenial/cassandra/snap updated
390. By Evan

Add bug reference.

391. By Evan

Correct default for edition.

392. By Evan

Prefer platform.dist to host.lsb_release

393. By Evan

Do not try to decode from a string

394. By Evan

Fix tests; reset log mocks between calls.

395. By Evan

Revert move from lsb_release to platform: https://bugs.python.org/issue1322#msg263313

Revision history for this message
Evan (ev) :
Revision history for this message
Stuart Bishop (stub) wrote :

I think this is past the point where it can land. I'm running tests.

review: Approve
Revision history for this message
Stuart Bishop (stub) wrote :

I needed to make some more changes, which at at lp:~stub/charms/trusty/cassandra/xenial. The charm is now multi-series, and I'm pushing it to a new home at https://launchpad.net/cassandra-charm ( git+ssh://git.launchpad.net/cassandra-charm ). Further work should land on the git branch (let me know if you have much outstanding work that can't be easily moved in).

There are no integration tests of the snap install yet. Which is fine, as there is no documentation for the new feature either :-) We should fix both of these issues on the git branch.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'config.yaml'
--- config.yaml 2016-02-26 16:47:03 +0000
+++ config.yaml 2016-06-29 15:55:10 +0000
@@ -74,16 +74,16 @@
74 type: string74 type: string
75 default: community75 default: community
76 description: >76 description: >
77 One of 'community' or 'dse'. 'community' uses the77 One of 'community', 'dse', or 'apache-snap'. 'community' uses the
78 Apache Cassandra packages. 'dse' is for DataStax78 Apache Cassandra packages. 'dse' is for DataStax Enterprise.
79 Enterprise. Selecting 'dse' overrides the jvm setting.79 Selecting 'dse' overrides the jvm setting. 'apache-snap' uses a
80 snap package of Apache Cassandra.
80 jre:81 jre:
81 type: string82 type: string
82 default: openjdk83 default: openjdk
83 description: >84 description: >
84 Which Java runtime environment to use. May be 'openjdk' or85 Which Java runtime environment to use. May be 'openjdk' or
85 'oracle'.86 'oracle'.
86
87 # Storage configuration87 # Storage configuration
88 wait_for_storage_broker:88 wait_for_storage_broker:
89 type: boolean89 type: boolean
9090
=== modified file 'hooks/actions.py'
--- hooks/actions.py 2016-06-09 10:59:24 +0000
+++ hooks/actions.py 2016-06-29 15:55:10 +0000
@@ -277,7 +277,9 @@
277@action277@action
278def install_cassandra_packages():278def install_cassandra_packages():
279 helpers.install_packages(helpers.get_cassandra_packages())279 helpers.install_packages(helpers.get_cassandra_packages())
280 if helpers.get_jre() != 'oracle':280 if helpers.get_cassandra_edition() == 'apache-snap':
281 helpers.install_cassandra_snap()
282 elif helpers.get_jre() != 'oracle':
281 subprocess.check_call(['update-java-alternatives',283 subprocess.check_call(['update-java-alternatives',
282 '--jre-headless',284 '--jre-headless',
283 '--set', 'java-1.8.0-openjdk-amd64'])285 '--set', 'java-1.8.0-openjdk-amd64'])
@@ -286,6 +288,7 @@
286@action288@action
287def ensure_cassandra_package_status():289def ensure_cassandra_package_status():
288 helpers.ensure_package_status(helpers.get_cassandra_packages())290 helpers.ensure_package_status(helpers.get_cassandra_packages())
291 helpers.ensure_cassandra_snap_installed()
289292
290293
291def _fetch_oracle_jre():294def _fetch_oracle_jre():
@@ -361,6 +364,8 @@
361def install_oracle_jre():364def install_oracle_jre():
362 if helpers.get_jre() != 'oracle':365 if helpers.get_jre() != 'oracle':
363 return366 return
367 if helpers.get_cassandra_edition() == 'apache-snap':
368 return
364369
365 tarball = _fetch_oracle_jre()370 tarball = _fetch_oracle_jre()
366 _install_oracle_jre_tarball(tarball)371 _install_oracle_jre_tarball(tarball)
@@ -368,6 +373,9 @@
368373
369@action374@action
370def emit_java_version():375def emit_java_version():
376 if helpers.get_cassandra_edition() == 'apache-snap':
377 return
378
371 # Log the version for posterity. Could be useful since Oracle JRE379 # Log the version for posterity. Could be useful since Oracle JRE
372 # security updates are not automated.380 # security updates are not automated.
373 version = subprocess.check_output(['java', '-version'],381 version = subprocess.check_output(['java', '-version'],
@@ -426,7 +434,7 @@
426 rack={}434 rack={}
427 ''').format(datacenter, rack)435 ''').format(datacenter, rack)
428 rackdc_path = helpers.get_cassandra_rackdc_file()436 rackdc_path = helpers.get_cassandra_rackdc_file()
429 host.write_file(rackdc_path, rackdc_properties.encode('UTF-8'))437 helpers.write_config(rackdc_path, rackdc_properties)
430438
431439
432def needs_reset_auth_keyspace_replication():440def needs_reset_auth_keyspace_replication():
433441
=== modified file 'hooks/helpers.py'
--- hooks/helpers.py 2016-06-09 10:59:24 +0000
+++ hooks/helpers.py 2016-06-29 15:55:10 +0000
@@ -125,6 +125,46 @@
125 dpkg.communicate(input=''.join(selections).encode('US-ASCII'))125 dpkg.communicate(input=''.join(selections).encode('US-ASCII'))
126126
127127
128# FOR CHARMHELPERS
129@logged
130def install_cassandra_snap():
131 '''Ensure that the Cassandra snap is installed at the current revision.
132 '''
133 cmd = ['snap', 'list', 'cassandra']
134 output = subprocess.check_output(cmd, universal_newlines=True)
135 if 'cassandra' not in output:
136 with autostart_disabled(['snap.cassandra.cassandra']):
137 subprocess.check_call(['snap', 'install', 'cassandra'])
138 else:
139 # snap will exit 1 if the snap is already the newest version.
140 # Filed as http://pad.lv/1595064
141 subprocess.call(['snap', 'refresh', 'cassandra'])
142
143 plug = 'cassandra:mount-observe'
144 slot = 'ubuntu-core:mount-observe'
145 subprocess.check_call(['snap', 'connect', plug, slot])
146
147
148# FOR CHARMHELPERS
149@logged
150def ensure_cassandra_snap_installed():
151 '''Check if the cassandra snap is installed and raise RuntimeError if it is
152 not.
153 '''
154 cmd = ['snap', 'list', 'cassandra']
155 output = subprocess.check_output(cmd, universal_newlines=True)
156 if 'cassandra' not in output:
157 raise RuntimeError('Cassandra snap not installed.')
158
159
160def get_snap_env(envar):
161 '''Return the value of an environment variable present in the snap wrapper
162 scripts.
163 '''
164 cmd = ['/snap/bin/cassandra.env-get', envar]
165 return subprocess.check_output(cmd, universal_newlines=True).strip('\n')
166
167
128def get_seed_ips():168def get_seed_ips():
129 '''Return the set of seed ip addresses.169 '''Return the set of seed ip addresses.
130170
@@ -149,7 +189,9 @@
149 '''189 '''
150 import relations190 import relations
151 storage = relations.StorageRelation()191 storage = relations.StorageRelation()
152 if storage.mountpoint:192 if get_cassandra_edition() == 'apache-snap':
193 root = get_snap_env('SNAP_DATA')
194 elif storage.mountpoint:
153 root = os.path.join(storage.mountpoint, 'cassandra')195 root = os.path.join(storage.mountpoint, 'cassandra')
154 else:196 else:
155 root = '/var/lib/cassandra'197 root = '/var/lib/cassandra'
@@ -169,10 +211,13 @@
169 component = os.sep211 component = os.sep
170 for p in absdir.split(os.sep)[1:-1]:212 for p in absdir.split(os.sep)[1:-1]:
171 component = os.path.join(component, p)213 component = os.path.join(component, p)
172 if not os.path.exists(p):214 if not os.path.exists(component):
173 host.mkdir(component)215 host.mkdir(component)
174 assert component == os.path.split(absdir)[0]216 assert component == os.path.split(absdir)[0]
175 host.mkdir(absdir, owner='cassandra', group='cassandra', perms=0o750)217 if get_cassandra_edition() == 'apache-snap':
218 host.mkdir(absdir, owner='root', group='root', perms=0o750)
219 else:
220 host.mkdir(absdir, owner='cassandra', group='cassandra', perms=0o750)
176 return absdir221 return absdir
177222
178223
@@ -277,6 +322,15 @@
277 host.write_file(backup_path, f.read(), perms=0o600)322 host.write_file(backup_path, f.read(), perms=0o600)
278323
279324
325def get_snap_version(snap):
326 '''Get the version string for an installed snap.'''
327 cmd = ['snap', 'list', snap]
328 out = subprocess.check_output(cmd, universal_newlines=True)
329 match = re.search('\n{}\s*(\S*)'.format(snap), out)
330 if match:
331 return match.groups(0)[0]
332
333
280# FOR CHARMHELPERS334# FOR CHARMHELPERS
281def get_package_version(package):335def get_package_version(package):
282 cache = fetch.apt_cache()336 cache = fetch.apt_cache()
@@ -305,22 +359,34 @@
305def get_cassandra_edition():359def get_cassandra_edition():
306 config = hookenv.config()360 config = hookenv.config()
307 edition = config['edition'].lower()361 edition = config['edition'].lower()
308 if edition not in ('community', 'dse'):362 if edition not in ('community', 'dse', 'apache-snap'):
309 hookenv.log('Unknown edition {!r}. Using community.'.format(edition),363 hookenv.log('Unknown edition {!r}. Using community.'.format(edition),
310 ERROR)364 ERROR)
311 edition = 'community'365 edition = 'community'
366 release = host.lsb_release()['DISTRIB_CODENAME']
367 if edition == 'apache-snap' and release in ['precise', 'trusty']:
368 msg = '{!r} cannot be used with {!r}. Using community.'
369 msg = msg.format(release, edition)
370 hookenv.log(msg, ERROR)
371 edition = 'community'
372
312 return edition373 return edition
313374
314375
315def get_cassandra_service():376def get_cassandra_service():
316 '''Cassandra upstart service'''377 '''Cassandra upstart service'''
317 if get_cassandra_edition() == 'dse':378 if get_cassandra_edition() == 'apache-snap':
379 return 'snap.cassandra.cassandra'
380 elif get_cassandra_edition() == 'dse':
318 return 'dse'381 return 'dse'
319 return 'cassandra'382 return 'cassandra'
320383
321384
322def get_cassandra_version():385def get_cassandra_version():
323 if get_cassandra_edition() == 'dse':386 edition = get_cassandra_edition()
387 if edition == 'apache-snap':
388 return get_snap_version('cassandra')
389 elif edition == 'dse':
324 dse_ver = get_package_version('dse-full')390 dse_ver = get_package_version('dse-full')
325 if not dse_ver:391 if not dse_ver:
326 return None392 return None
@@ -338,12 +404,37 @@
338404
339405
340def get_cassandra_config_dir():406def get_cassandra_config_dir():
341 if get_cassandra_edition() == 'dse':407 edition = get_cassandra_edition()
408 if edition == 'apache-snap':
409 return get_snap_env('CASSANDRA_CONF')
410 elif edition == 'dse':
342 return '/etc/dse/cassandra'411 return '/etc/dse/cassandra'
343 else:412 else:
344 return '/etc/cassandra'413 return '/etc/cassandra'
345414
346415
416def get_snap_config_file(filename):
417 '''Get the contents of the named configuration file from the current snap
418 data directory.
419 '''
420 cmd = ['/snap/bin/cassandra.config-get', filename]
421 return subprocess.check_output(cmd, universal_newlines=True)
422
423
424def set_snap_config_file(filename, contents):
425 '''Install a new copy of the configuration file with the provided contents
426 in the current snap data directory.
427 '''
428 cmd = ['/snap/bin/cassandra.config-set', filename]
429 cs = subprocess.Popen(cmd, stdin=subprocess.PIPE, universal_newlines=True)
430 _, err = cs.communicate(input=contents)
431 if err:
432 hookenv.log('Error calling {}:\n{}'.format(' '.join(cmd), err))
433 if cs.returncode != 0:
434 msg = '{} exited with code {}'.format(' '.join(cmd), cs.returncode)
435 raise RuntimeError(msg)
436
437
347def get_cassandra_yaml_file():438def get_cassandra_yaml_file():
348 return os.path.join(get_cassandra_config_dir(), "cassandra.yaml")439 return os.path.join(get_cassandra_config_dir(), "cassandra.yaml")
349440
@@ -359,7 +450,10 @@
359450
360def get_cassandra_pid_file():451def get_cassandra_pid_file():
361 edition = get_cassandra_edition()452 edition = get_cassandra_edition()
362 if edition == 'dse':453 if edition == 'apache-snap':
454 home = get_snap_env('CASSANDRA_HOME')
455 pid_file = os.path.join(home, 'cassandra.pid')
456 elif edition == 'dse':
363 pid_file = "/var/run/dse/dse.pid"457 pid_file = "/var/run/dse/dse.pid"
364 else:458 else:
365 pid_file = "/var/run/cassandra/cassandra.pid"459 pid_file = "/var/run/cassandra/cassandra.pid"
@@ -367,16 +461,22 @@
367461
368462
369def get_cassandra_packages():463def get_cassandra_packages():
370 edition = get_cassandra_edition()464 packages = set()
371 if edition == 'dse':
372 packages = set(['dse-full'])
373 else:
374 packages = set(['cassandra']) # 'cassandra-tools'
375465
376 packages.add('ntp')466 packages.add('ntp')
377 packages.add('run-one')467 packages.add('run-one')
378 packages.add('netcat')468 packages.add('netcat')
379469
470 edition = get_cassandra_edition()
471 if edition == 'apache-snap':
472 packages.add('snapd')
473 return packages
474
475 if edition == 'dse':
476 packages.add('dse-full')
477 else:
478 packages.add('cassandra') # 'cassandra-tools'
479
380 jre = get_jre()480 jre = get_jre()
381 if jre == 'oracle':481 if jre == 'oracle':
382 # We can't use a packaged version of the Oracle JRE, as we482 # We can't use a packaged version of the Oracle JRE, as we
@@ -464,6 +564,7 @@
464 # Guard against changing perms on a running db. Although probably564 # Guard against changing perms on a running db. Although probably
465 # harmless, it causes shutil.chown() to fail.565 # harmless, it causes shutil.chown() to fail.
466 assert not is_cassandra_running()566 assert not is_cassandra_running()
567
467 db_dirs = get_all_database_directories()568 db_dirs = get_all_database_directories()
468 ensure_database_directory(db_dirs['commitlog_directory'])569 ensure_database_directory(db_dirs['commitlog_directory'])
469 ensure_database_directory(db_dirs['saved_caches_directory'])570 ensure_database_directory(db_dirs['saved_caches_directory'])
@@ -549,7 +650,19 @@
549650
550651
551def encrypt_password(password):652def encrypt_password(password):
552 return bcrypt.hashpw(password, bcrypt.gensalt())653 password = password.encode('ascii')
654 # Java doesn't understand bcrypt 2b yet:
655 # cassandra.AuthenticationFailed: Failed to authenticate to localhost:
656 # code=0000 [Server error] message="java.lang.IllegalArgumentException:
657 # Invalid salt revision"
658 try:
659 salt = bcrypt.gensalt(prefix=b'2a')
660 # Newer versions of bcrypt return a bytestring.
661 return bcrypt.hashpw(password, salt).decode('ascii')
662 except TypeError:
663 # Trusty bcrypt doesn't support prefix=
664 salt = bcrypt.gensalt()
665 return bcrypt.hashpw(password, salt)
553666
554667
555@logged668@logged
@@ -563,6 +676,7 @@
563 hookenv.log('Creating SUPERUSER {}'.format(username))676 hookenv.log('Creating SUPERUSER {}'.format(username))
564 else:677 else:
565 hookenv.log('Creating user {}'.format(username))678 hookenv.log('Creating user {}'.format(username))
679
566 if has_cassandra_version('2.2'):680 if has_cassandra_version('2.2'):
567 query(session,681 query(session,
568 'INSERT INTO system_auth.roles '682 'INSERT INTO system_auth.roles '
@@ -609,7 +723,11 @@
609723
610724
611def get_cqlshrc_path():725def get_cqlshrc_path():
612 return os.path.expanduser('~root/.cassandra/cqlshrc')726 if get_cassandra_edition() == 'apache-snap':
727 base = get_cassandra_config_dir()
728 return os.path.join(base, 'cql/cqlshrc')
729 else:
730 return os.path.expanduser('~root/.cassandra/cqlshrc')
613731
614732
615def superuser_username():733def superuser_username():
@@ -672,7 +790,11 @@
672790
673791
674def nodetool(*cmd, timeout=120):792def nodetool(*cmd, timeout=120):
675 cmd = ['nodetool'] + [str(i) for i in cmd]793 if get_cassandra_edition() == 'apache-snap':
794 nodetool_cmd = '/snap/bin/cassandra.nodetool'
795 else:
796 nodetool_cmd = 'nodetool'
797 cmd = [nodetool_cmd] + [str(i) for i in cmd]
676 i = 0798 i = 0
677 until = time.time() + timeout799 until = time.time() + timeout
678 for _ in backoff('nodetool to work'):800 for _ in backoff('nodetool to work'):
@@ -710,24 +832,39 @@
710 return len(get_bootstrapped_ips())832 return len(get_bootstrapped_ips())
711833
712834
835def write_config(path, contents):
836 '''Write out the config file at path with the provided contents, encoding
837 in UTF-8 first. If using a snap edition, write to the snap config
838 directory.
839 '''
840 if get_cassandra_edition() == 'apache-snap':
841 set_snap_config_file(os.path.basename(path), contents)
842 else:
843 contents = contents.encode('UTF-8')
844 host.write_file(path, contents)
845
846
713def read_cassandra_yaml():847def read_cassandra_yaml():
714 cassandra_yaml_path = get_cassandra_yaml_file()848 if get_cassandra_edition() == 'apache-snap':
715 with open(cassandra_yaml_path, 'rb') as f:849 f = get_snap_config_file('cassandra.yaml')
716 return yaml.safe_load(f)850 return yaml.safe_load(f)
851 else:
852 cassandra_yaml_path = get_cassandra_yaml_file()
853 with open(cassandra_yaml_path, 'rb') as f:
854 return yaml.safe_load(f)
717855
718856
719@logged857@logged
720def write_cassandra_yaml(cassandra_yaml):858def write_cassandra_yaml(cassandra_yaml):
721 cassandra_yaml_path = get_cassandra_yaml_file()859 write_config(get_cassandra_yaml_file(), yaml.safe_dump(cassandra_yaml))
722 host.write_file(cassandra_yaml_path,
723 yaml.safe_dump(cassandra_yaml).encode('UTF-8'))
724860
725861
726def configure_cassandra_yaml(overrides={}, seeds=None):862def configure_cassandra_yaml(overrides={}, seeds=None):
727 cassandra_yaml_path = get_cassandra_yaml_file()
728 config = hookenv.config()863 config = hookenv.config()
729864
730 maybe_backup(cassandra_yaml_path) # Its comments may be useful.865 if get_cassandra_edition() != 'apache-snap':
866 cassandra_yaml_path = get_cassandra_yaml_file()
867 maybe_backup(cassandra_yaml_path) # Its comments may be useful.
731868
732 cassandra_yaml = read_cassandra_yaml()869 cassandra_yaml = read_cassandra_yaml()
733870
@@ -784,6 +921,7 @@
784921
785922
786def is_cassandra_running():923def is_cassandra_running():
924 edition = get_cassandra_edition()
787 pid_file = get_cassandra_pid_file()925 pid_file = get_cassandra_pid_file()
788926
789 try:927 try:
@@ -797,7 +935,12 @@
797 # is not running.935 # is not running.
798 os.kill(pid, 0)936 os.kill(pid, 0)
799937
800 if subprocess.call(["nodetool", "status"],938 if edition == 'apache-snap':
939 # /snap/bin is not on PATH for the root user.
940 nodetool = '/snap/bin/cassandra.nodetool'
941 else:
942 nodetool = 'nodetool'
943 if subprocess.call([nodetool, "status"],
801 stdout=subprocess.DEVNULL,944 stdout=subprocess.DEVNULL,
802 stderr=subprocess.DEVNULL) == 0:945 stderr=subprocess.DEVNULL) == 0:
803 hookenv.log(946 hookenv.log(
804947
=== modified file 'tests/test_helpers.py'
--- tests/test_helpers.py 2016-03-17 10:54:10 +0000
+++ tests/test_helpers.py 2016-06-29 15:55:10 +0000
@@ -163,6 +163,10 @@
163 # Autostart wasn't messed with.163 # Autostart wasn't messed with.
164 self.assertFalse(autostart_disabled.called)164 self.assertFalse(autostart_disabled.called)
165165
166 def test_encrypt_password(self):
167 self.assertEqual(type(helpers.encrypt_password('')), str)
168
169
166 @patch('subprocess.Popen')170 @patch('subprocess.Popen')
167 def test_ensure_package_status(self, popen):171 def test_ensure_package_status(self, popen):
168 for status in ['install', 'hold']:172 for status in ['install', 'hold']:
@@ -380,7 +384,10 @@
380 hookenv.config()['edition'] = 'dse'384 hookenv.config()['edition'] = 'dse'
381 self.assertEqual(helpers.get_jre(), 'oracle')385 self.assertEqual(helpers.get_jre(), 'oracle')
382386
383 def test_get_cassandra_edition(self):387 @patch('charmhelpers.core.host.lsb_release')
388 def test_get_cassandra_edition(self, lsb_release):
389 lsb_release.return_value = {'DISTRIB_CODENAME': 'trusty'}
390
384 hookenv.config()['edition'] = 'community'391 hookenv.config()['edition'] = 'community'
385 self.assertEqual(helpers.get_cassandra_edition(), 'community')392 self.assertEqual(helpers.get_cassandra_edition(), 'community')
386393
@@ -389,10 +396,21 @@
389396
390 self.assertFalse(hookenv.log.called)397 self.assertFalse(hookenv.log.called)
391398
399 hookenv.log.reset_mock()
392 hookenv.config()['edition'] = 'typo' # Default to community400 hookenv.config()['edition'] = 'typo' # Default to community
393 self.assertEqual(helpers.get_cassandra_edition(), 'community')401 self.assertEqual(helpers.get_cassandra_edition(), 'community')
394 hookenv.log.assert_any_call(ANY, hookenv.ERROR) # Logs an error.402 hookenv.log.assert_any_call(ANY, hookenv.ERROR) # Logs an error.
395403
404 hookenv.log.reset_mock()
405 hookenv.config()['edition'] = 'apache-snap' # Default to community
406 self.assertEqual(helpers.get_cassandra_edition(), 'community')
407 hookenv.log.assert_any_call(ANY, hookenv.ERROR) # Logs an error.
408
409 lsb_release.reset_mock()
410 lsb_release.return_value = {'DISTRIB_CODENAME': 'xenial'}
411 hookenv.config()['edition'] = 'apache-snap'
412 self.assertEqual(helpers.get_cassandra_edition(), 'apache-snap')
413
396 @patch('helpers.get_cassandra_edition')414 @patch('helpers.get_cassandra_edition')
397 def test_get_cassandra_service(self, get_edition):415 def test_get_cassandra_service(self, get_edition):
398 get_edition.return_value = 'whatever'416 get_edition.return_value = 'whatever'
@@ -460,6 +478,30 @@
460 '/foo/cassandra-rackdc.properties')478 '/foo/cassandra-rackdc.properties')
461479
462 @patch('helpers.get_cassandra_edition')480 @patch('helpers.get_cassandra_edition')
481 def test_write_config(self, get_edition):
482 get_edition.return_value = 'whatever'
483 expected = 'some config'
484 with tempfile.TemporaryDirectory() as tmpdir:
485 path = os.path.join(tmpdir, 'foo')
486 helpers.write_config(path, expected)
487 with open(path, 'r') as fp:
488 self.assertEqual(fp.read(), expected)
489
490 @patch('subprocess.Popen')
491 @patch('helpers.get_cassandra_edition')
492 def test_write_config_snap(self, get_edition, popen):
493 get_edition.return_value = 'apache-snap'
494 popen.return_value.returncode = 0
495 popen.return_value.communicate.return_value = ('', '')
496 helpers.write_config('/some/path/to/config.yaml', 'some config')
497 expected = 'some config'
498 self.assertEqual(
499 [call(['/snap/bin/cassandra.config-set', 'config.yaml'],
500 stdin=subprocess.PIPE, universal_newlines=True),
501 call().communicate(input=expected)], popen.mock_calls)
502
503
504 @patch('helpers.get_cassandra_edition')
463 def test_get_cassandra_pid_file(self, get_edition):505 def test_get_cassandra_pid_file(self, get_edition):
464 get_edition.return_value = 'whatever'506 get_edition.return_value = 'whatever'
465 self.assertEqual(helpers.get_cassandra_pid_file(),507 self.assertEqual(helpers.get_cassandra_pid_file(),

Subscribers

People subscribed via source and target branches

to all changes: