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