153 lines
5.9 KiB
Python
Executable File
153 lines
5.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import os
|
|
import re
|
|
import unittest
|
|
import subprocess
|
|
|
|
import amulet
|
|
|
|
|
|
class TestActions(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.d = amulet.Deployment(series='xenial')
|
|
cls.d.add('etcd')
|
|
cls.d.add('easyrsa', 'cs:~containers/easyrsa')
|
|
cls.d.configure('etcd', {'channel': '3.0/stable'})
|
|
cls.d.relate('easyrsa:client', 'etcd:certificates')
|
|
cls.d.setup(timeout=1200)
|
|
cls.d.sentry.wait_for_messages({'etcd':
|
|
re.compile('Healthy*|Unhealthy*')})
|
|
# cls.d.sentry.wait()
|
|
cls.etcd = cls.d.sentry['etcd']
|
|
|
|
def test_health_check(self):
|
|
"""
|
|
Trigger health action
|
|
"""
|
|
action_id = self.etcd[0].run_action('health')
|
|
outcome = self.d.action_fetch(action_id,
|
|
timeout=7200,
|
|
raise_on_timeout=True,
|
|
full_output=True)
|
|
self.assertEqual(outcome['status'], 'completed')
|
|
self.assertTrue("cluster is healthy" in outcome['results']['result-map']['message'])
|
|
|
|
def test_snapshot_restore(self):
|
|
"""
|
|
Trigger snapshot and restore actions
|
|
"""
|
|
# Load dummy data
|
|
self.load_data()
|
|
self.assertTrue(self.is_data_present('v2'))
|
|
self.assertTrue(self.is_data_present('v3'))
|
|
|
|
filenames = {}
|
|
for dataset in ['v2', 'v3']:
|
|
# Take snapshot of data
|
|
action_id = self.etcd[0].run_action('snapshot', {'keys-version': dataset})
|
|
outcome = self.d.action_fetch(action_id,
|
|
timeout=7200,
|
|
raise_on_timeout=True,
|
|
full_output=True)
|
|
self.assertEqual(outcome['status'], 'completed')
|
|
cpcmd = outcome['results']['copy']['cmd']
|
|
subprocess.check_call(cpcmd.split())
|
|
filenames[dataset] = os.path.basename(outcome['results']['snapshot']['path'])
|
|
|
|
self.delete_data()
|
|
self.assertFalse(self.is_data_present('v2'))
|
|
self.assertFalse(self.is_data_present('v3'))
|
|
|
|
# Restore v2 data
|
|
cmd = 'juju attach etcd snapshot=%s' % filenames['v2']
|
|
subprocess.check_call(cmd.split())
|
|
action_id = self.etcd[0].run_action('restore')
|
|
outcome = self.d.action_fetch(action_id,
|
|
timeout=7200,
|
|
raise_on_timeout=True,
|
|
full_output=True)
|
|
self.assertEqual(outcome['status'], 'completed')
|
|
self.assertTrue(self.is_data_present('v2'))
|
|
self.assertFalse(self.is_data_present('v3'))
|
|
|
|
# Restore v3 data
|
|
cmd = 'juju attach etcd snapshot=%s' % filenames['v3']
|
|
subprocess.check_call(cmd.split())
|
|
action_id = self.etcd[0].run_action('restore')
|
|
outcome = self.d.action_fetch(action_id,
|
|
timeout=7200,
|
|
raise_on_timeout=True,
|
|
full_output=True)
|
|
self.assertEqual(outcome['status'], 'completed')
|
|
self.assertFalse(self.is_data_present('v2'))
|
|
self.assertTrue(self.is_data_present('v3'))
|
|
|
|
def load_data(self):
|
|
"""
|
|
Load dummy data
|
|
|
|
"""
|
|
certs = "ETCDCTL_KEY_FILE=/var/snap/etcd/common/client.key " \
|
|
"ETCDCTL_CERT_FILE=/var/snap/etcd/common/client.crt " \
|
|
"ETCDCTL_CA_FILE=/var/snap/etcd/common/ca.crt " \
|
|
"ETCDCTL_KEY=/var/snap/etcd/common/client.key " \
|
|
"ETCDCTL_CERT=/var/snap/etcd/common/client.crt " \
|
|
"ETCDCTL_CACERT=/var/snap/etcd/common/ca.crt"
|
|
|
|
cmd = '{} ETCDCTL_API=2 /snap/bin/etcdctl set /etcd2key etcd2value'.format(certs)
|
|
self.etcd[0].run(cmd)
|
|
cmd = '{} ETCDCTL_API=3 /snap/bin/etcdctl --endpoints=http://localhost:4001 ' \
|
|
'put etcd3key etcd3value'.format(certs)
|
|
self.etcd[0].run(cmd)
|
|
|
|
def is_data_present(self, version):
|
|
'''
|
|
Check if we have the data present on the datastore of the version
|
|
Args:
|
|
version: v2 or v3 etcd datastore
|
|
|
|
Returns: True if the data is present
|
|
|
|
'''
|
|
certs = "ETCDCTL_KEY_FILE=/var/snap/etcd/common/client.key " \
|
|
"ETCDCTL_CERT_FILE=/var/snap/etcd/common/client.crt " \
|
|
"ETCDCTL_CA_FILE=/var/snap/etcd/common/ca.crt " \
|
|
"ETCDCTL_KEY=/var/snap/etcd/common/client.key " \
|
|
"ETCDCTL_CERT=/var/snap/etcd/common/client.crt " \
|
|
"ETCDCTL_CACERT=/var/snap/etcd/common/ca.crt"
|
|
|
|
if version == 'v2':
|
|
cmd = '{} ETCDCTL_API=2 /snap/bin/etcdctl ls'.format(certs)
|
|
data = self.etcd[0].run(cmd)
|
|
return 'etcd2key' in data[0]
|
|
elif version == 'v3':
|
|
cmd = '{} ETCDCTL_API=3 /snap/bin/etcdctl --endpoints=http://localhost:4001 ' \
|
|
'get "" --prefix --keys-only'.format(certs)
|
|
data = self.etcd[0].run(cmd)
|
|
return 'etcd3key' in data[0]
|
|
else:
|
|
return False
|
|
|
|
def delete_data(self):
|
|
'''
|
|
Delete all dummy data on etcd
|
|
'''
|
|
certs = "ETCDCTL_KEY_FILE=/var/snap/etcd/common/client.key " \
|
|
"ETCDCTL_CERT_FILE=/var/snap/etcd/common/client.crt " \
|
|
"ETCDCTL_CA_FILE=/var/snap/etcd/common/ca.crt " \
|
|
"ETCDCTL_KEY=/var/snap/etcd/common/client.key " \
|
|
"ETCDCTL_CERT=/var/snap/etcd/common/client.crt " \
|
|
"ETCDCTL_CACERT=/var/snap/etcd/common/ca.crt"
|
|
|
|
cmd = '{} ETCDCTL_API=2 /snap/bin/etcdctl rm /etcd2key'.format(certs)
|
|
self.etcd[0].run(cmd)
|
|
cmd = '{} ETCDCTL_API=3 /snap/bin/etcdctl --endpoints=http://localhost:4001 ' \
|
|
'del etcd3key'.format(certs)
|
|
self.etcd[0].run(cmd)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|