github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/jujupy/workloads.py (about) 1 # This file is part of JujuPy, a library for driving the Juju CLI. 2 # Copyright 2013-2018 Canonical Ltd. 3 # 4 # This program is free software: you can redistribute it and/or modify it 5 # under the terms of the Lesser GNU General Public License version 3, as 6 # published by the Free Software Foundation. 7 # 8 # This program is distributed in the hope that it will be useful, but WITHOUT 9 # ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, 10 # SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser 11 # GNU General Public License for more details. 12 # 13 # You should have received a copy of the Lesser GNU General Public License 14 # along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 from __future__ import print_function 17 18 try: 19 from urllib2 import urlopen 20 except ImportError: 21 from urllib.request import urlopen 22 23 from jujucharm import local_charm_path 24 import logging 25 import os 26 import requests 27 28 from jujupy.wait_condition import ( 29 AgentsIdle, 30 AllApplicationActive, 31 AllApplicationWorkloads, 32 ) 33 from jujupy.utility import ( 34 get_unit_public_ip, 35 temp_dir, 36 ) 37 38 39 __metaclass__ = type 40 41 log = logging.getLogger(__name__) 42 43 44 def deploy_mediawiki_with_db(client): 45 client.deploy('cs:percona-cluster') 46 client.wait_for_started() 47 client.wait_for_workloads() 48 client.juju('run', ('--unit', 'percona-cluster/0', 'leader-get')) 49 50 # Using local mediawiki charm due to db connect bug. 51 # Once that's fixed we can use from the charmstore. 52 charm_path = local_charm_path( 53 charm='mediawiki', juju_ver=client.version) 54 client.deploy(charm_path) 55 client.wait_for_started() 56 # mediawiki workload is blocked ('Database needed') until a db 57 # relation is successfully made. 58 client.juju('relate', ('mediawiki:db', 'percona-cluster:db')) 59 client.wait_for_workloads() 60 client.wait_for_started() 61 client.juju('expose', 'mediawiki') 62 client.wait_for_workloads() 63 client.wait_for_started() 64 65 66 def assert_mediawiki_is_responding(client): 67 log.debug('Assert mediawiki is responding.') 68 status = client.get_status() 69 [wiki_unit_name] = [ 70 k for k, v in status.get_applications()['mediawiki']['units'].items() 71 if v.get('leader', False)] 72 wiki_ip = get_unit_public_ip(client, wiki_unit_name) 73 resp = requests.get('http://{}'.format(wiki_ip)) 74 if not resp.ok: 75 raise AssertionError('Mediawiki not responding; {}: {}'.format( 76 resp.status_code, resp.reason 77 )) 78 if '<title>Please set name of wiki</title>' not in resp.content: 79 raise AssertionError('Got unexpected mediawiki page content: {}'.format(resp.content)) 80 81 def deploy_keystone_with_db(client): 82 client.deploy('cs:percona-cluster') 83 client.wait_for_started() 84 client.wait_for_workloads() 85 client.juju('run', ('--unit', 'percona-cluster/0', 'leader-get')) 86 87 # use a charm which is under development by 88 # canonical to try to avoid rot. 89 client.deploy('cs:keystone') 90 client.wait_for_started() 91 client.juju('relate', ('keystone:shared-db', 'percona-cluster:shared-db')) 92 client.wait_for_workloads() 93 client.wait_for_started() 94 client.juju('expose', 'keystone') 95 client.wait_for_workloads() 96 client.wait_for_started() 97 98 def assert_keystone_is_responding(client): 99 log.debug('Assert keystone is responding.') 100 status = client.get_status() 101 [keystone_unit_name] = [ 102 k for k, v in status.get_applications()['keystone']['units'].items() 103 if v.get('leader', False)] 104 dash_ip = get_unit_public_ip(client, keystone_unit_name) 105 resp = requests.get('http://{}:5000'.format(dash_ip)) 106 if not resp.ok: 107 raise AssertionError('keystone not responding; {}: {}'.format( 108 resp.status_code, resp.reason 109 )) 110 if '{"versions": {"values":' not in resp.content: 111 raise AssertionError('Got unexpected keystone page content: {}'.format(resp.content)) 112 113 def deploy_simple_server_to_new_model( 114 client, model_name, resource_contents=None, series='xenial'): 115 # As per bug LP:1709773 deploy 2 primary apps and have a subordinate 116 # related to both 117 new_model = client.add_model(client.env.clone(model_name)) 118 application = deploy_simple_resource_server( 119 new_model, resource_contents, series) 120 _, deploy_complete = new_model.deploy('cs:ubuntu', series=series) 121 new_model.wait_for(deploy_complete) 122 new_model.deploy('cs:nrpe', series=series) 123 new_model.juju('add-relation', ('nrpe', application)) 124 new_model.juju('add-relation', ('nrpe', 'ubuntu')) 125 # Need to wait for the subordinate charms too. 126 new_model.wait_for(AllApplicationActive()) 127 new_model.wait_for(AllApplicationWorkloads()) 128 new_model.wait_for(AgentsIdle(['nrpe/0', 'nrpe/1'])) 129 assert_deployed_charm_is_responding(new_model, resource_contents) 130 131 return new_model, application 132 133 134 def deploy_simple_resource_server( 135 client, resource_contents=None, series='xenial'): 136 application_name = 'simple-resource-http' 137 log.info('Deploying charm: '.format(application_name)) 138 charm_path = local_charm_path( 139 charm=application_name, juju_ver=client.version) 140 # Create a temp file which we'll use as the resource. 141 if resource_contents is not None: 142 with temp_dir() as temp: 143 index_file = os.path.join(temp, 'index.html') 144 with open(index_file, 'wt') as f: 145 f.write(resource_contents) 146 client.deploy( 147 charm_path, 148 series=series, 149 resource='index={}'.format(index_file)) 150 else: 151 client.deploy(charm_path, series=series) 152 153 client.wait_for_started() 154 client.wait_for_workloads() 155 client.juju('expose', (application_name)) 156 return application_name 157 158 159 def deploy_dummy_source_to_new_model(client, model_name): 160 new_model_client = client.add_model(client.env.clone(model_name)) 161 charm_path = local_charm_path( 162 charm='dummy-source', juju_ver=new_model_client.version) 163 new_model_client.deploy(charm_path) 164 new_model_client.wait_for_started() 165 new_model_client.set_config('dummy-source', {'token': 'one'}) 166 new_model_client.wait_for_workloads() 167 return new_model_client 168 169 170 def assert_deployed_charm_is_responding(client, expected_output=None): 171 """Ensure that the deployed simple-server charm is still responding.""" 172 # Set default value if needed. 173 if expected_output is None: 174 expected_output = 'simple-server.' 175 ipaddress = get_unit_public_ip(client, 'simple-resource-http/0') 176 if expected_output != get_server_response(ipaddress): 177 raise AssertionError('Server charm is not responding as expected.') 178 179 180 def get_server_response(ipaddress): 181 resp = urlopen('http://{}'.format(ipaddress)) 182 charset = response_charset(resp) 183 return resp.read().decode(charset).rstrip() 184 185 186 def response_charset(resp): 187 try: 188 charset = [ 189 h for h in resp.headers['content-type'].split('; ') 190 if h.startswith('charset')][0] 191 charset = charset.split('=')[1] 192 except (IndexError, KeyError): 193 charset = 'utf-8' 194 195 return charset