github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/repository/trusty/haproxy/tests/10_deploy_test.py (about)

     1  #!/usr/bin/python3
     2  
     3  # This Amulet test deploys haproxy and related charms.
     4  
     5  import os
     6  import amulet
     7  import requests
     8  import base64
     9  import yaml
    10  import time
    11  
    12  d = amulet.Deployment(series='trusty')
    13  # Add the haproxy charm to the deployment.
    14  d.add('haproxy')
    15  d.add('apache2', units=2)
    16  
    17  # Get the directory this way to load the file when CWD is different.
    18  path = os.path.abspath(os.path.dirname(__file__))
    19  template_path = os.path.join(path, 'default_apache.tmpl')
    20  # Read in the Apache2 default template file.
    21  with open(template_path) as f:
    22      template = f.read()
    23      encodedTemplate = base64.b64encode(template.encode('utf-8'))
    24  # Create a dictionary with configuration values for apache2.
    25  configuration = {'vhost_http_template': encodedTemplate.decode('ascii')}
    26  # Apache2 needs a base64 encoded template to configure the web site.
    27  d.configure('apache2', configuration)
    28  
    29  # Relate the haproxy to apache2.
    30  d.relate('haproxy:reverseproxy', 'apache2:website')
    31  # Make the haproxy visible to the outside world.
    32  d.expose('haproxy')
    33  
    34  # The number of seconds to wait for the environment to setup.
    35  seconds = 900
    36  try:
    37      # Execute the deployer with the current mapping.
    38      d.setup(timeout=seconds)
    39      # Wait for the relation to finish the transations.
    40      d.sentry.wait(seconds)
    41  except amulet.helpers.TimeoutError:
    42      message = 'The environment did not setup in %d seconds.' % seconds
    43      # The SKIP status enables skip or fail the test based on configuration.
    44      amulet.raise_status(amulet.SKIP, msg=message)
    45  except:
    46      raise
    47  
    48  # Test that haproxy is acting as the proxy for apache2.
    49  
    50  # Get the haproxy unit.
    51  haproxy_unit = d.sentry['haproxy'][0]
    52  haproxy_address = haproxy_unit.info['public-address']
    53  page = requests.get('http://%s/index.html' % haproxy_address)
    54  # Raise an error if the page does not load through haproxy.
    55  page.raise_for_status()
    56  print('Successfully got the Apache2 web page through haproxy IP address.')
    57  
    58  # Test that sticky session cookie is present
    59  if page.cookies.get('SRVNAME') != 'S0':
    60      msg = 'Missing or invalid sticky session cookie value: %s' % page.cookies.get('SRVNAME')
    61      amulet.raise_status(amulet.FAIL, msg=msg)
    62  
    63  # Test that the apache2 relation data is saved on the haproxy server.
    64  
    65  # Get the sentry for apache and get the private IP address.
    66  apache_unit = d.sentry['apache2'][0]
    67  # Get the relation.
    68  relation = apache_unit.relation('website', 'haproxy:reverseproxy')
    69  # Get the private address from the relation.
    70  apache_private = relation['private-address']
    71  
    72  print('Private address of the apache2 relation ', apache_private)
    73  
    74  # Grep the configuration file for the private address
    75  output, code = haproxy_unit.run('grep %s /etc/haproxy/haproxy.cfg' %
    76                                  apache_private)
    77  if code == 0:
    78      print('Found the relation IP address in the haproxy configuration file!')
    79      print(output)
    80  else:
    81      print(output)
    82      message = 'Unable to find the Apache IP address %s in the haproxy ' \
    83                'configuration file.' % apache_private
    84      amulet.raise_status(amulet.FAIL, msg=message)
    85  
    86  # Test SSL termination
    87  d.configure('haproxy', {
    88      'source': 'backports',
    89      'ssl_cert': 'SELFSIGNED',
    90      'services': yaml.safe_dump([
    91          {'service_name': 'apache',
    92           'service_host': '0.0.0.0',
    93           'service_port': 80,
    94           'service_options': [
    95               'mode http', 'balance leastconn', 'option httpchk GET / HTTP/1.0'
    96           ],
    97           'servers': [
    98               ['apache', apache_private, 80, 'maxconn 50']]},
    99          {'service_name': 'apache-ssl',
   100           'service_port': 443,
   101           'service_host': '0.0.0.0',
   102           'service_options': [
   103               'mode http', 'balance leastconn', 'option httpchk GET / HTTP/1.0'
   104           ],
   105           'crts': ['DEFAULT'],
   106           'servers': [['apache', apache_private, 80, 'maxconn 50']]}])
   107  })
   108  time.sleep(10)
   109  d.sentry.wait(seconds)
   110  
   111  # We need a retry loop here, since there's no way to tell when the new
   112  # configuration is in place.
   113  url = 'http://%s/index.html' % haproxy_address
   114  secure_url = 'https://%s/index.html' % haproxy_address
   115  retries = 10
   116  for i in range(retries):
   117      try:
   118          page = requests.get(url)
   119          page.raise_for_status()
   120          page = requests.get(secure_url, verify=False)
   121          page.raise_for_status()
   122          success = True
   123      except requests.exceptions.ConnectionError:
   124          if i == retries - 1:
   125              # This was the last one, let's fail
   126              raise
   127          time.sleep(6)
   128      else:
   129          break
   130  
   131  print('Successfully got the Apache2 web page through haproxy SSL termination.')
   132  
   133  apache_unit2 = d.sentry['apache2'][1]
   134  apache_private2 = apache_unit2.run("unit-get private-address")[0]
   135  
   136  # Create a file on the second apache unit's www directory.
   137  apache_unit2.run("echo foo > /var/www/html/foo")
   138  
   139  d.configure('haproxy', {
   140      'services': yaml.safe_dump([
   141          {'service_name': 'apache',
   142           'service_host': '0.0.0.0',
   143           'service_port': 80,
   144           'service_options': [
   145               'mode http', 'balance leastconn', 'option httpchk GET / HTTP/1.0',
   146               'acl foo path_beg -i /foo', 'use_backend foo if foo',
   147           ],
   148           'servers': [
   149               ['apache', apache_private, 80, 'maxconn 50']],
   150           'backends': [
   151               {'backend_name': 'foo',
   152                'servers': [
   153                    ['apache2', apache_private2, 80, 'maxconn 50']]}
   154           ]}])
   155  })
   156  time.sleep(10)
   157  d.sentry.wait(seconds)
   158  
   159  # Let's exercise our URL-based routing by trying to fetch a URL that will
   160  # only work for the second apache unit (which is configured as server
   161  # of the extra backend).
   162  url = 'http://%s/foo' % haproxy_address
   163  
   164  # We need a retry loop here, since there's no way to tell when the new
   165  # configuration is in place.
   166  retries = 10
   167  for i in range(retries):
   168      try:
   169          page = requests.get(url)
   170          page.raise_for_status()
   171      except:
   172          if i == retries - 1:
   173              # This was the last one, let's fail
   174              raise
   175          time.sleep(6)
   176      else:
   177          break
   178  
   179  print('Successfully got the /foo URL from the second Apache unit.')
   180  
   181  # Send a message that the tests are complete.
   182  print('The haproxy tests are complete.')