Add HTTPS test for the toolchain

Change-Id: Ib073584d5a38cd6b736f7ab48688c86e0528cbed
This commit is contained in:
Igor Degtiarov 2016-07-01 19:00:47 +03:00 committed by Simon Pasquier
parent 4a9e048cf3
commit f93a153298
8 changed files with 205 additions and 12 deletions

View File

@ -120,3 +120,11 @@ class PluginApi(object):
self.helpers.power_off_node(target_node)
self.helpers.wait_for_vip_migration(
target_node, self.settings.role_name, vip_name)
def get_http_protocol(self, tls_parameter='tls_enabled'):
"""Return the HTTP protocol configured for the plugin (http or https).
"""
protocol = 'http'
if self.helpers.get_plugin_setting(self.settings.name, tls_parameter):
protocol = 'https'
return protocol

View File

@ -24,6 +24,8 @@ class ElasticsearchPluginApi(base_test.PluginApi):
def __init__(self):
super(ElasticsearchPluginApi, self).__init__()
self._es_client = None
self._kibana_port = None
self._kibana_protocol = None
@property
def es(self):
@ -32,6 +34,21 @@ class ElasticsearchPluginApi(base_test.PluginApi):
[{'host': self.get_plugin_vip(), 'port': 9200}])
return self._es_client
@property
def kibana_port(self):
if self._kibana_port is None:
if self.kibana_protocol == 'http':
self._kibana_port = 80
else:
self._kibana_port = 443
return self._kibana_port
@property
def kibana_protocol(self):
if self._kibana_protocol is None:
self._kibana_protocol = self.get_http_protocol()
return self._kibana_protocol
def get_plugin_settings(self):
return plugin_settings
@ -51,7 +68,8 @@ class ElasticsearchPluginApi(base_test.PluginApi):
return "http://{}:9200/{}".format(self.get_plugin_vip(), path)
def get_kibana_url(self):
return "http://{}:80/".format(self.get_plugin_vip())
return "{0}://{1}:{2}/".format(
self.kibana_protocol, self.get_plugin_vip(), self.kibana_port)
def check_plugin_online(self):
elasticsearch_url = self.get_elasticsearch_url()

View File

@ -17,10 +17,19 @@ import socket
from proboscis import asserts
import requests
from requests.packages.urllib3 import poolmanager
from stacklight_tests.helpers import helpers
from stacklight_tests.helpers import remote_ops
class TestHTTPAdapter(requests.adapters.HTTPAdapter):
"""Custom transport adapter to disable host checking in https requests."""
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = poolmanager.PoolManager(assert_hostname=False)
def check_http_get_response(url, expected_code=200, msg=None, **kwargs):
"""Perform a HTTP GET request and assert that the HTTP server replies with
the expected code.
@ -34,8 +43,11 @@ def check_http_get_response(url, expected_code=200, msg=None, **kwargs):
:returns: HTTP response object
:rtype: requests.Response
"""
s = requests.Session()
s.mount("https://", TestHTTPAdapter())
cert = helpers.get_fixture("https/rootCA.pem")
msg = msg or "%s responded with {0}, expected {1}" % url
r = requests.get(url, **kwargs)
r = s.get(url, verify=cert, **kwargs)
asserts.assert_equal(
r.status_code, expected_code, msg.format(r.status_code, expected_code))
return r

View File

@ -111,6 +111,35 @@ class PluginHelper(object):
self.env.admin_actions.install_plugin(
plugin_file_name=os.path.basename(plugin_path))
def get_plugin_setting(self, plugin, parameter):
"""Return the given parameter's value for the plugin.
:param plugin: name of the plugin.
:type plugin: str
:param parameter: name of the parameter.
:type name: str
:returns: parameter's value
"""
asserts.assert_true(
self.fuel_web.check_plugin_exists(self.cluster_id, plugin),
"Plugin {0} isn't found.".format(plugin))
attributes = self.nailgun_client.get_cluster_attributes(
self.cluster_id)
attributes = attributes['editable'][plugin]
value = None
for item in attributes['metadata']['versions']:
if (parameter in item and
item['metadata']['plugin_id'] ==
attributes['metadata']['chosen_id']):
value = item[parameter]['value']
break
asserts.assert_is_not_none(
value, "Could not find parameter {0} for plugin {1}".format(
parameter, plugin))
return value
def activate_plugin(self, name, version, options=None, strict=False):
"""Enable and configure a plugin for the cluster.
@ -122,7 +151,7 @@ class PluginHelper(object):
:type options: dict
:param strict: whether or not to fail when setting an unknown option
(default: False).
:type options: boolean
:type strict: boolean
:returns: None
"""
if options is None:

View File

@ -26,15 +26,27 @@ class InfluxdbPluginApi(base_test.PluginApi):
def __init__(self):
super(InfluxdbPluginApi, self).__init__()
self._grafana_port = None
self._grafana_protocol = None
@property
def grafana_port(self):
if self._grafana_port is None:
self._grafana_port = 80
if self.grafana_protocol == 'http':
self._grafana_port = 80
else:
self._grafana_port = 443
# TODO(pasquier-s): remove this code once all plugins use the
# standard ports
if self.checkers.check_port(self.get_plugin_vip(), 8000):
self._grafana_port = 8000
return self._grafana_port
@property
def grafana_protocol(self):
if self._grafana_protocol is None:
self._grafana_protocol = self.get_http_protocol()
return self._grafana_protocol
def get_plugin_settings(self):
return plugin_settings
@ -51,8 +63,9 @@ class InfluxdbPluginApi(base_test.PluginApi):
return self.helpers.get_plugin_vip(self.settings.vip_name)
def get_grafana_url(self, path=''):
return "http://{0}:{1}/{2}".format(self.get_plugin_vip(),
self.grafana_port, path)
return "{0}://{1}:{2}/{3}".format(self.grafana_protocol,
self.get_plugin_vip(),
self.grafana_port, path)
def get_influxdb_url(self, path=''):
return "http://{0}:8086/{1}".format(self.get_plugin_vip(), path)

View File

@ -28,15 +28,27 @@ class InfraAlertingPluginApi(base_test.PluginApi):
def __init__(self):
super(InfraAlertingPluginApi, self).__init__()
self._nagios_port = None
self._nagios_protocol = None
@property
def nagios_port(self):
if self._nagios_port is None:
self._nagios_port = 80
if self.nagios_protocol == 'http':
self._nagios_port = 80
else:
self._nagios_port = 443
# TODO(pasquier-s): remove this code once all plugins use the
# standard ports
if self.checkers.check_port(self.get_plugin_vip(), 8001):
self._nagios_port = 8001
return self._nagios_port
@property
def nagios_protocol(self):
if self._nagios_protocol is None:
self._nagios_protocol = self.get_http_protocol()
return self._nagios_protocol
def get_plugin_settings(self):
return infra_alerting_plugin_settings
@ -72,13 +84,15 @@ class InfraAlertingPluginApi(base_test.PluginApi):
)
def get_authenticated_nagios_url(self):
return "http://{0}:{1}@{2}:{3}".format(self.settings.nagios_user,
self.settings.nagios_password,
self.get_plugin_vip(),
self.nagios_port)
return "{0}://{1}:{2}@{3}:{4}".format(self.nagios_protocol,
self.settings.nagios_user,
self.settings.nagios_password,
self.get_plugin_vip(),
self.nagios_port)
def get_nagios_url(self):
return "http://{0}:{1}".format(self.get_plugin_vip(), self.nagios_port)
return "{0}://{1}:{2}".format(self.nagios_protocol,
self.get_plugin_vip(), self.nagios_port)
def open_nagios_page(self, link_text, anchor):
driver = self.ui_tester.get_driver(self.get_authenticated_nagios_url(),

View File

@ -54,6 +54,7 @@ def import_tests():
from stacklight_tests.toolchain import test_dedicated_environment # noqa
from stacklight_tests.toolchain import test_detached_plugins # noqa
from stacklight_tests.toolchain import test_functional # noqa
from stacklight_tests.toolchain import test_https_plugins # noqa
from stacklight_tests.toolchain import test_network_templates # noqa
from stacklight_tests.toolchain import test_post_install # noqa
from stacklight_tests.toolchain import test_reduced_footprint # noqa

View File

@ -0,0 +1,98 @@
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from fuelweb_test.helpers.decorators import log_snapshot_after_test
from fuelweb_test import logger
from proboscis import test
from stacklight_tests.helpers import helpers
from stacklight_tests.toolchain import api
@test(groups=["https"])
class TestToolchainHTTPs(api.ToolchainApi):
"""Class for smoke testing the LMA Toolchain plugins."""
@test(depends_on_groups=['prepare_slaves_3'],
groups=["https", "deploy_toolchain_with_https", "toolchain",
"deploy"])
@log_snapshot_after_test
def deploy_toolchain_with_https(self):
"""Install the LMA Toolchain plugins and check it exists
Scenario:
1. Upload the LMA Toolchain plugins to the master node
2. Install the plugins
3. Create the cluster
4. Uplaod script for ssl certificate creation
5. Create ssl certificate for influxdb_grafana plugin
6. Create ssl certificate for elasticsearch_kibana plugin
7. Create ssl certificate for lma_infrastructure_alerting plugin
8. Enable and configure TLS option in plugins
9. Deploy the cluster
10. Check that LMA Toolchain plugins are running
11. Run OSTF
Duration 120m
"""
self.env.revert_snapshot("ready_with_3_slaves")
self.prepare_plugins()
self.helpers.create_cluster(name=self.__class__.__name__)
self.activate_plugins()
plugins_ssl = {
"kibana": self.ELASTICSEARCH_KIBANA,
"grafana": self.INFLUXDB_GRAFANA,
"nagios": self.LMA_INFRASTRUCTURE_ALERTING,
}
with self.env.d_env.get_admin_remote() as remote:
remote.upload(
helpers.get_fixture("https/create_certificate.sh"),
"/tmp")
for name, plugin in plugins_ssl.items():
self._activate_ssl_plugin(name, plugin, remote)
self.helpers.deploy_cluster(self.settings.base_nodes)
self.check_plugins_online()
self.helpers.run_ostf()
self.env.make_snapshot("https_plugins", is_make=True)
@staticmethod
def _activate_ssl_plugin(name, plugin, remote):
"""Creates certificate and activate ssl option in plugin."""
logger.info(
"Create certificate and configure tls in plugin {}".format(
plugin.get_plugin_settings().name))
ssl_cert = {}
ssl_cert["name"] = "{}.pem".format(name)
remote.execute(
"cd /tmp && bash -x create_certificate.sh {}.fuel.local".
format(name), verbose=True
)
with remote.open("/tmp/{}.pem".format(name)) as f:
ssl_cert["content"] = f.read()
plugin.activate_plugin(options={
"tls_enabled/value": True,
"{}_ssl_cert/value".format(name): ssl_cert
})