neutron-lbaas-dashboard-4.0.0/ 0000775 0001751 0001751 00000000000 13245512321 016234 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/package.json 0000666 0001751 0001751 00000001615 13245511613 020532 0 ustar zuul zuul 0000000 0000000 {
"version": "4.0.0b1",
"private": true,
"name": "neutron-lbaas-dashboard",
"description": "Neutron LBaaS v2 Dashboard (deprecated)",
"repository": "none",
"license": "Apache 2.0",
"devDependencies": {
"eslint": "1.10.3",
"eslint-config-openstack": "1.2.4",
"eslint-plugin-angular": "1.0.1",
"jasmine-core": "2.4.1",
"karma": "1.1.2",
"karma-chrome-launcher": "1.0.1",
"karma-cli": "1.0.1",
"karma-coverage": "1.1.1",
"karma-jasmine": "1.0.2",
"karma-ng-html2js-preprocessor": "1.0.0",
"karma-phantomjs-launcher": "1.0.4",
"karma-threshold-reporter": "0.1.15",
"phantomjs-prebuilt": "2.1.14"
},
"scripts": {
"postinstall": "neutron_lbaas_dashboard/post_install.sh",
"test": "karma start neutron_lbaas_dashboard/karma.conf.js --single-run",
"lint": "eslint --no-color neutron_lbaas_dashboard/static"
},
"dependencies": {}
}
neutron-lbaas-dashboard-4.0.0/releasenotes/ 0000775 0001751 0001751 00000000000 13245512321 020725 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/releasenotes/notes/ 0000775 0001751 0001751 00000000000 13245512321 022055 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/releasenotes/notes/bp-horizon-lbaas-v2-ui-ba7e4c97a0460f85.yaml 0000666 0001751 0001751 00000001672 13245511613 031304 0 ustar zuul zuul 0000000 0000000 ---
features:
- A new dashboard wizard for Neutron LBaaS version 2. Allows you to create a
version 2 load balancer and related resources such as a listener, pool,
pool members, and health monitor.
- A view of all the existing version 2 load balancers.
- Ability to view details of a version 2 load balancer and drill down to see
details for the listener, pool, pool member, and health monitor resources.
- Ability to create, update, and delete the version 2 load balancer, listener,
pool, pool member, and health monitor resources.
- Ability to associate and disassociate floating IP addresses for a version
2 load balancer.
- Ability to choose from SSL certificates stored by the key-manager service
when creating a version 2 listener using the TERMINATED_HTTPS protocol.
- Ability to choose from existing instances from the compute service or
specify external members when adding members to a version 2 pool.
././@LongLink 0000000 0000000 0000000 00000000153 00000000000 011214 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/releasenotes/notes/neutron-lbaas-dashboard-deprecation-a3c910ababba8e78.yaml neutron-lbaas-dashboard-4.0.0/releasenotes/notes/neutron-lbaas-dashboard-deprecation-a3c910ababba8e70000666 0001751 0001751 00000000665 13245511613 033341 0 ustar zuul zuul 0000000 0000000 ---
prelude: >
As of the Queens release, neutron-lbaas-dashboard is now deprecated and
being replaced by the octavia-dashboard project. Please see the FAQ
for more information:
https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation
deprecations:
- |
The neutron-lbaas-dashboard project is now deprecated. Please see the FAQ
for more information:
https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation
neutron-lbaas-dashboard-4.0.0/doc/ 0000775 0001751 0001751 00000000000 13245512321 017001 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/doc/source/ 0000775 0001751 0001751 00000000000 13245512321 020301 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/doc/source/usage.rst 0000666 0001751 0001751 00000006116 13245511613 022150 0 ustar zuul zuul 0000000 0000000 ==========
User Guide
==========
.. warning::
Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation
Load-Balancer-as-a-Service (LBaaS) enables networking to distribute incoming
requests evenly among designated instances. This distribution ensures that
the workload is shared predictably among instances and enables more effective
use of system resources. Use one of these load-balancing methods to distribute
incoming requests:
* Round robin: Rotates requests evenly between multiple instances.
* Source IP: Requests from a unique source IP address are consistently
directed to the same instance.
* Least connections: Allocates requests to the instance with the
least number of active connections.
As an end user, you can create and manage load balancers and related
objects for users in various projects. You can also delete load balancers
and related objects.
LBaaS v2 has several new concepts to understand:
Load balancer
The load balancer occupies a neutron network port and
has an IP address assigned from a subnet.
Listener
Each port that listens for traffic on a particular load balancer is
configured separately and tied to the load balancer. Multiple listeners can
be associated with the same load balancer.
Pool
A pool is a group of hosts that sits behind the load balancer and
serves traffic through the load balancer.
Member
Members are the actual IP addresses that receive traffic from
the load balancer. Members are associated with pools.
Health monitor
Members may go offline from time to time and health monitors
diverts traffic away from members that are not responding properly.
Health monitors are associated with pools.
View existing load balancers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#. Log in to the OpenStack dashboard.
#. On the :guilabel:`Project` tab, open the
:guilabel:`Network` tab, and click the
:guilabel:`Load Balancers` category.
This view shows the list of existing load balancers. To view details
of any of the load balancers, click on the specific load balancer.
Create a load balancer
~~~~~~~~~~~~~~~~~~~~~~
#. Log in to the OpenStack dashboard.
#. On the :guilabel:`Project` tab, open the
:guilabel:`Network` tab, and click the
:guilabel:`Load Balancers` category.
#. Click the :guilabel:`Create Load Balancer` button.
Use the concepts described in the overview section to fill in
the necessary information about the load balancer you want to create.
Keep in mind, the health checks routinely run against each instance
within a target load balancer and the result of the health check is
used to determine if the instance receives new connections.
.. note::
A message indicates whether the action succeeded.
Delete a load balancer
~~~~~~~~~~~~~~~~~~~~~~
#. Select the load balancer you want to delete
and click the :guilabel:`Delete Load Balancer` button.
To be deleted successfully, a load balancer must not
have any listeners or pools associated with
it. The delete action is also available in the
:guilabel:`Actions` column for the individual load balancers.
neutron-lbaas-dashboard-4.0.0/doc/source/readme.rst 0000666 0001751 0001751 00000000036 13245511613 022274 0 ustar zuul zuul 0000000 0000000 .. include:: ../../README.rst
neutron-lbaas-dashboard-4.0.0/doc/source/reference.rst 0000666 0001751 0001751 00000000265 13245511613 023001 0 ustar zuul zuul 0000000 0000000 =========
Reference
=========
Indices and search
------------------
.. toctree::
:hidden:
contributor/modules/modules
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
neutron-lbaas-dashboard-4.0.0/doc/source/conf.py 0000777 0001751 0001751 00000007550 13245511613 021617 0 ustar zuul zuul 0000000 0000000 # -*- coding: utf-8 -*-
# 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.
import logging
import os
import sys
from sphinx import apidoc
import django
sys.path.insert(0, os.path.abspath('../..'))
sys.path.insert(0, os.path.abspath('.'))
logging.getLogger('openstack_dashboard.settings').setLevel(logging.ERROR)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'openstack_dashboard.settings')
django.setup()
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'openstackdocstheme',
'sphinx.ext.autodoc',
'sphinx.ext.coverage',
# 'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'neutron-lbaas-dashboard'
copyright = u'2013, OpenStack Foundation'
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
html_theme = 'openstackdocs'
html_theme_options = {
'display_toc': False
}
html_static_path = []
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
# intersphinx_mapping = {'http://docs.python.org/': None}
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['neutron-lbaas-dashboard.']
# TODO(mordred) We should extract this into a sphinx plugin
def run_apidoc(_):
cur_dir = os.path.abspath(os.path.dirname(__file__))
out_dir = os.path.join(cur_dir, 'contributor', 'modules')
module = os.path.join(cur_dir, '..', '..', 'neutron_lbaas_dashboard')
# Keep the order of arguments same as the sphinx-apidoc help, otherwise it
# would cause unexpected errors:
# sphinx-apidoc [options] -o
# [exclude_pattern, ...]
apidoc.main([
'--force',
'-o',
out_dir,
module,
'neutron_lbaas_dashboard/tests',
'neutron_lbaas_dashboard/enabled',
'neutron_lbaas_dashboard/locale',
'neutron_lbaas_dashboard/static',
'neutron_lbaas_dashboard/post_install.sh',
'neutron_lbaas_dashboard/karma.conf.js'
])
def setup(app):
app.connect('builder-inited', run_apidoc)
neutron-lbaas-dashboard-4.0.0/doc/source/contributing.rst 0000666 0001751 0001751 00000000113 13245511613 023542 0 ustar zuul zuul 0000000 0000000 ============
Contributing
============
.. include:: ../../CONTRIBUTING.rst
neutron-lbaas-dashboard-4.0.0/doc/source/index.rst 0000666 0001751 0001751 00000001113 13245511613 022143 0 ustar zuul zuul 0000000 0000000 .. neutron-lbaas-dashboard documentation master file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to neutron-lbaas-dashboard's documentation!
========================================================
.. warning::
Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation
Contents:
.. toctree::
:maxdepth: 2
readme
installation
usage
contributing
reference
neutron-lbaas-dashboard-4.0.0/doc/source/installation.rst 0000666 0001751 0001751 00000001447 13245511613 023547 0 ustar zuul zuul 0000000 0000000 ============
Installation
============
.. warning::
Neutron-lbaas-dashboard is now deprecated. Please see the FAQ: https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation
At the command line::
$ sudo pip install neutron-lbaas-dashboard
Enable the plugin::
$ cp /usr/local/lib/python2.7/dist-packages/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py /opt/stack/horizon/openstack_dashboard/enabled/
Note: This file may have installed in a different location depending on your
host configuration. For example, on CentOS it may be in
/usr/lib/python2.7/site-packages.
Run the Django update commands (answer 'yes')::
$ /opt/stack/horizon/manage.py collectstatic
$ /opt/stack/horizon/manage.py compress
Restart Apache::
$ sudo service apache2 restart
neutron-lbaas-dashboard-4.0.0/doc/requirements.txt 0000666 0001751 0001751 00000000426 13245511613 022274 0 ustar zuul zuul 0000000 0000000 # The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
openstackdocstheme>=1.18.1 # Apache-2.0
sphinx!=1.6.6,>=1.6.2 # BSD
neutron-lbaas-dashboard-4.0.0/devstack/ 0000775 0001751 0001751 00000000000 13245512321 020040 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/devstack/README.rst 0000666 0001751 0001751 00000001471 13245511613 021537 0 ustar zuul zuul 0000000 0000000 ==========================================
Neutron LBaaS v2 dashboard devstack plugin
==========================================
This directory contains the neutron-lbaas-dashboard devstack plugin.
To enable the plugin, add the following to your local.conf:
enable_plugin neutron-lbaas-dashboard [GITREF]
where
is the URL of a neutron-lbaas-dashboard repository
[GITREF] is an optional git ref (branch/ref/tag). The default is master.
For example:
enable_plugin neutron-lbaas-dashboard https://git.openstack.org/openstack/neutron-lbaas-dashboard
Once you enable the plugin in your local.conf, ensure ``horizon`` and
``q-lbaasv2`` services are enabled. If both of them are enabled,
neutron-lbaas-dashboard will be enabled automatically
neutron-lbaas-dashboard-4.0.0/devstack/settings 0000666 0001751 0001751 00000000437 13245511613 021634 0 ustar zuul zuul 0000000 0000000 NEUTRON_LBAAS_DASHBOARD_DIR=$DEST/neutron-lbaas-dashboard
NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_NAME=_1481_project_ng_loadbalancersv2_panel.py
NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_PATH=$NEUTRON_LBAAS_DASHBOARD_DIR/neutron_lbaas_dashboard/enabled/$NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_NAME
neutron-lbaas-dashboard-4.0.0/devstack/plugin.sh 0000666 0001751 0001751 00000002300 13245511613 021672 0 ustar zuul zuul 0000000 0000000 function neutron_lbaas_dashboard_install {
setup_develop $NEUTRON_LBAAS_DASHBOARD_DIR
}
function neutron_lbaas_dashboard_configure {
cp $NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_PATH \
$HORIZON_DIR/openstack_dashboard/local/enabled/
}
if is_service_enabled horizon && is_service_enabled q-lbaasv2; then
if [[ "$1" == "stack" && "$2" == "install" ]]; then
# Perform installation of service source
echo_summary "Installing neutron-lbaas-dashboard"
neutron_lbaas_dashboard_install
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
echo_summary "Configuring neutron-lbaas-dashboard"
neutron_lbaas_dashboard_configure
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
# Initialize and start the LBaaS service
echo_summary "Initializing neutron-lbaas-dashboard"
fi
fi
if [[ "$1" == "unstack" ]]; then
# Shut down LBaaS dashboard services
:
fi
if [[ "$1" == "clean" ]]; then
# Remove state and transient data
# Remember clean.sh first calls unstack.sh
# Remove lbaas-dashboard enabled file and pyc
rm -f "$HORIZON_DIR"/openstack_dashboard/local/enabled/"$NEUTRON_LBAAS_DASHBOARD_ENABLE_FILE_NAME"*
fi
neutron-lbaas-dashboard-4.0.0/babel-djangojs.cfg 0000666 0001751 0001751 00000001060 13245511613 021561 0 ustar zuul zuul 0000000 0000000 [extractors]
# We use a custom extractor to find translatable strings in AngularJS
# templates. The extractor is included in horizon.utils for now.
# See http://babel.pocoo.org/docs/messages/#referencing-extraction-methods for
# details on how this works.
angular = horizon.utils.babel_extract_angular:extract_angular
[javascript: **.js]
# We need to look into all static folders for HTML files.
# The **/static ensures that we also search within
# .../dashboards/XYZ/static which will ensure
# that plugins are also translated.
[angular: **/static/**.html]
neutron-lbaas-dashboard-4.0.0/LICENSE 0000666 0001751 0001751 00000023637 13245511613 017261 0 ustar zuul zuul 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/ 0000775 0001751 0001751 00000000000 13245512321 023077 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/enabled/ 0000775 0001751 0001751 00000000000 13245512321 024471 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/enabled/__init__.py 0000666 0001751 0001751 00000000000 13245511613 026575 0 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000150 00000000000 011211 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel0000666 0001751 0001751 00000002274 13245511613 033675 0 ustar zuul zuul 0000000 0000000 # Copyright 2015 IBM Corp.
#
# 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.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'ngloadbalancersv2'
# The slug of the dashboard the PANEL is associated with. Required.
PANEL_DASHBOARD = 'project'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'network'
# Python panel class of the PANEL to be added.
ADD_PANEL = (
'neutron_lbaas_dashboard.dashboards.project.ngloadbalancersv2.panel'
'.NGLoadBalancers')
ADD_INSTALLED_APPS = ['neutron_lbaas_dashboard']
ADD_ANGULAR_MODULES = ['horizon.dashboard.project.lbaasv2']
ADD_SCSS_FILES = ['dashboard/project/lbaasv2/lbaasv2.scss']
AUTO_DISCOVER_STATIC_FILES = True
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/ 0000775 0001751 0001751 00000000000 13245512321 023650 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/__init__.py 0000666 0001751 0001751 00000000000 13245511613 025754 0 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/rest/ 0000775 0001751 0001751 00000000000 13245512321 024625 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/rest/__init__.py 0000666 0001751 0001751 00000002077 13245511613 026751 0 ustar zuul zuul 0000000 0000000 # Copyright 2015 IBM Corp.
#
# 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.
"""This package holds the REST API that supports the LBaaS v2 dashboard
Javascript code.
It is not intended to be used outside of Horizon, and makes no promises of
stability or fitness for purpose outside of that scope.
It does not promise to adhere to the general OpenStack API Guidelines set out
in https://wiki.openstack.org/wiki/APIChangeGuidelines.
"""
# import REST API modules here
from neutron_lbaas_dashboard.api.rest import barbican # noqa
from neutron_lbaas_dashboard.api.rest import lbaasv2 # noqa
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/rest/lbaasv2.py 0000666 0001751 0001751 00000064241 13245511613 026545 0 ustar zuul zuul 0000000 0000000 # Copyright 2015 IBM Corp.
#
# 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.
"""API over the neutron LBaaS v2 service.
"""
from six.moves import _thread as thread
from time import sleep
from django.views import generic
from horizon import conf
from openstack_dashboard.api import neutron
from openstack_dashboard.api.rest import urls
from openstack_dashboard.api.rest import utils as rest_utils
neutronclient = neutron.neutronclient
def poll_loadbalancer_status(request, loadbalancer_id, callback,
from_state='PENDING_UPDATE', to_state='ACTIVE',
callback_kwargs=None):
"""Poll for the status of the load balancer.
Polls for the status of the load balancer and calls a function when the
status changes to a specified state.
:param request: django request object
:param loadbalancer_id: id of the load balancer to poll
:param callback: function to call when polling is complete
:param from_state: initial expected state of the load balancer
:param to_state: state to check for
:param callback_kwargs: kwargs to pass into the callback function
"""
interval = conf.HORIZON_CONFIG['ajax_poll_interval'] / 1000.0
status = from_state
while status == from_state:
sleep(interval)
lb = neutronclient(request).show_loadbalancer(
loadbalancer_id).get('loadbalancer')
status = lb['provisioning_status']
if status == to_state:
kwargs = {'loadbalancer_id': loadbalancer_id}
if callback_kwargs:
kwargs.update(callback_kwargs)
callback(request, **kwargs)
def create_loadbalancer(request):
data = request.DATA
spec = {
'vip_subnet_id': data['loadbalancer']['subnet']
}
if data['loadbalancer'].get('name'):
spec['name'] = data['loadbalancer']['name']
if data['loadbalancer'].get('description'):
spec['description'] = data['loadbalancer']['description']
if data['loadbalancer'].get('ip'):
spec['vip_address'] = data['loadbalancer']['ip']
loadbalancer = neutronclient(request).create_loadbalancer(
{'loadbalancer': spec}).get('loadbalancer')
if data.get('listener'):
# There is work underway to add a new API to LBaaS v2 that will
# allow us to pass in all information at once. Until that is
# available we use a separate thread to poll for the load
# balancer status and create the other resources when it becomes
# active.
args = (request, loadbalancer['id'], create_listener)
kwargs = {'from_state': 'PENDING_CREATE'}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
return loadbalancer
def create_listener(request, **kwargs):
"""Create a new listener.
"""
data = request.DATA
listenerSpec = {
'protocol': data['listener']['protocol'],
'protocol_port': data['listener']['port'],
'loadbalancer_id': kwargs['loadbalancer_id']
}
if data['listener'].get('name'):
listenerSpec['name'] = data['listener']['name']
if data['listener'].get('description'):
listenerSpec['description'] = data['listener']['description']
if data.get('certificates'):
listenerSpec['default_tls_container_ref'] = data['certificates'][0]
listenerSpec['sni_container_refs'] = data['certificates']
listener = neutronclient(request).create_listener(
{'listener': listenerSpec}).get('listener')
if data.get('pool'):
args = (request, kwargs['loadbalancer_id'], create_pool)
kwargs = {'callback_kwargs': {'listener_id': listener['id']}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
return listener
def create_pool(request, **kwargs):
"""Create a new pool.
"""
data = request.DATA
poolSpec = {
'protocol': data['pool']['protocol'],
'lb_algorithm': data['pool']['method'],
'listener_id': kwargs['listener_id']
}
if data['pool'].get('name'):
poolSpec['name'] = data['pool']['name']
if data['pool'].get('description'):
poolSpec['description'] = data['pool']['description']
pool = neutronclient(request).create_lbaas_pool(
{'pool': poolSpec}).get('pool')
if data.get('members'):
args = (request, kwargs['loadbalancer_id'], add_member)
kwargs = {'callback_kwargs': {'pool_id': pool['id'],
'index': 0}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
elif data.get('monitor'):
args = (request, kwargs['loadbalancer_id'], create_health_monitor)
kwargs = {'callback_kwargs': {'pool_id': pool['id']}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
return pool
def create_health_monitor(request, **kwargs):
"""Create a new health monitor for a pool.
"""
data = request.DATA
monitorSpec = {
'type': data['monitor']['type'],
'delay': data['monitor']['interval'],
'timeout': data['monitor']['timeout'],
'max_retries': data['monitor']['retry'],
'pool_id': kwargs['pool_id']
}
if data['monitor'].get('method'):
monitorSpec['http_method'] = data['monitor']['method']
if data['monitor'].get('path'):
monitorSpec['url_path'] = data['monitor']['path']
if data['monitor'].get('status'):
monitorSpec['expected_codes'] = data['monitor']['status']
return neutronclient(request).create_lbaas_healthmonitor(
{'healthmonitor': monitorSpec}).get('healthmonitor')
def add_member(request, **kwargs):
"""Add a member to a pool.
"""
data = request.DATA
members = data.get('members')
pool_id = kwargs.get('pool_id')
if kwargs.get('members_to_add'):
members_to_add = kwargs['members_to_add']
index = [members.index(member) for member in members
if member['id'] == members_to_add[0]][0]
loadbalancer_id = data.get('loadbalancer_id')
else:
index = kwargs.get('index')
loadbalancer_id = kwargs.get('loadbalancer_id')
member = members[index]
memberSpec = {
'address': member['address'],
'protocol_port': member['port'],
'subnet_id': member['subnet']
}
if member.get('weight'):
memberSpec['weight'] = member['weight']
member = neutronclient(request).create_lbaas_member(
pool_id, {'member': memberSpec}).get('member')
index += 1
if kwargs.get('members_to_add'):
args = (request, loadbalancer_id, update_member_list)
members_to_add = kwargs['members_to_add']
members_to_add.pop(0)
kwargs = {'callback_kwargs': {
'existing_members': kwargs.get('existing_members'),
'members_to_add': members_to_add,
'members_to_delete': kwargs.get('members_to_delete'),
'pool_id': pool_id}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
elif len(members) > index:
args = (request, loadbalancer_id, add_member)
kwargs = {'callback_kwargs': {'pool_id': pool_id,
'index': index}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
elif data.get('monitor'):
args = (request, loadbalancer_id, create_health_monitor)
kwargs = {'callback_kwargs': {'pool_id': pool_id}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
return member
def remove_member(request, **kwargs):
"""Remove a member from the pool.
"""
data = request.DATA
loadbalancer_id = data.get('loadbalancer_id')
pool_id = kwargs.get('pool_id')
if kwargs.get('members_to_delete'):
members_to_delete = kwargs['members_to_delete']
member_id = members_to_delete.pop(0)
neutronclient(request).delete_lbaas_member(member_id, pool_id)
args = (request, loadbalancer_id, update_member_list)
kwargs = {'callback_kwargs': {
'existing_members': kwargs.get('existing_members'),
'members_to_add': kwargs.get('members_to_add'),
'members_to_delete': members_to_delete}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
def update_loadbalancer(request, **kwargs):
"""Update a load balancer.
"""
data = request.DATA
spec = {}
loadbalancer_id = kwargs.get('loadbalancer_id')
if data['loadbalancer'].get('name'):
spec['name'] = data['loadbalancer']['name']
if data['loadbalancer'].get('description'):
spec['description'] = data['loadbalancer']['description']
return neutronclient(request).update_loadbalancer(
loadbalancer_id, {'loadbalancer': spec}).get('loadbalancer')
def update_listener(request, **kwargs):
"""Update a listener.
"""
data = request.DATA
listener_spec = {}
listener_id = data['listener'].get('id')
loadbalancer_id = data.get('loadbalancer_id')
if data['listener'].get('name'):
listener_spec['name'] = data['listener']['name']
if data['listener'].get('description'):
listener_spec['description'] = data['listener']['description']
listener = neutronclient(request).update_listener(
listener_id, {'listener': listener_spec}).get('listener')
if data.get('pool'):
args = (request, loadbalancer_id, update_pool)
thread.start_new_thread(poll_loadbalancer_status, args)
return listener
def update_pool(request, **kwargs):
"""Update a pool.
"""
data = request.DATA
pool_spec = {}
pool_id = data['pool'].get('id')
loadbalancer_id = data.get('loadbalancer_id')
if data['pool'].get('name'):
pool_spec['name'] = data['pool']['name']
if data['pool'].get('description'):
pool_spec['description'] = data['pool']['description']
pools = neutronclient(request).update_lbaas_pool(
pool_id, {'pool': pool_spec}).get('pools')
# Assemble the lists of member id's to add and remove, if any exist
tenant_id = request.user.project_id
request_member_data = data.get('members', [])
existing_members = neutronclient(request).list_lbaas_members(
pool_id, tenant_id=tenant_id).get('members')
(members_to_add, members_to_delete) = get_members_to_add_remove(
request_member_data, existing_members)
if members_to_add or members_to_delete:
args = (request, loadbalancer_id, update_member_list)
kwargs = {'callback_kwargs': {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete,
'pool_id': pool_id}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
elif data.get('monitor'):
args = (request, loadbalancer_id, update_monitor)
thread.start_new_thread(poll_loadbalancer_status, args)
return pools
def update_monitor(request, **kwargs):
"""Update a health monitor.
"""
data = request.DATA
monitor_spec = {}
monitor_id = data['monitor']['id']
if data['monitor'].get('interval'):
monitor_spec['delay'] = data['monitor']['interval']
if data['monitor'].get('timeout'):
monitor_spec['timeout'] = data['monitor']['timeout']
if data['monitor'].get('retry'):
monitor_spec['max_retries'] = data['monitor']['retry']
if data['monitor'].get('method'):
monitor_spec['http_method'] = data['monitor']['method']
if data['monitor'].get('path'):
monitor_spec['url_path'] = data['monitor']['path']
if data['monitor'].get('status'):
monitor_spec['expected_codes'] = data['monitor']['status']
healthmonitor = neutronclient(request).update_lbaas_healthmonitor(
monitor_id, {'healthmonitor': monitor_spec}).get('healthmonitor')
return healthmonitor
def update_member_list(request, **kwargs):
"""Update the list of members by adding or removing the necessary members.
"""
data = request.DATA
loadbalancer_id = data.get('loadbalancer_id')
pool_id = kwargs.get('pool_id')
existing_members = kwargs.get('existing_members')
members_to_add = kwargs.get('members_to_add')
members_to_delete = kwargs.get('members_to_delete')
if members_to_delete:
kwargs = {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete,
'pool_id': pool_id}
remove_member(request, **kwargs)
elif members_to_add:
kwargs = {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete,
'pool_id': pool_id}
add_member(request, **kwargs)
elif data.get('monitor'):
args = (request, loadbalancer_id, update_monitor)
thread.start_new_thread(poll_loadbalancer_status, args)
def get_members_to_add_remove(request_member_data, existing_members):
new_member_ids = [member['id'] for member in request_member_data]
existing_member_ids = [member['id'] for member in existing_members]
members_to_add = [member_id for member_id in new_member_ids
if member_id not in existing_member_ids]
members_to_delete = [member_id for member_id in existing_member_ids
if member_id not in new_member_ids]
return members_to_add, members_to_delete
def add_floating_ip_info(request, loadbalancers):
"""Add floating IP address info to each load balancer.
"""
floating_ips = neutron.tenant_floating_ip_list(request)
for lb in loadbalancers:
floating_ip = {}
associated_ip = next((fip for fip in floating_ips
if fip['fixed_ip'] == lb['vip_address']), None)
if associated_ip is not None:
floating_ip['id'] = associated_ip['id']
floating_ip['ip'] = associated_ip['ip']
lb['floating_ip'] = floating_ip
@urls.register
class LoadBalancers(generic.View):
"""API for load balancers.
"""
url_regex = r'lbaas/loadbalancers/$'
@rest_utils.ajax()
def get(self, request):
"""List load balancers for current project.
The listing result is an object with property "items".
"""
tenant_id = request.user.project_id
loadbalancers = neutronclient(request).list_loadbalancers(
tenant_id=tenant_id).get('loadbalancers')
if request.GET.get('full') and neutron.floating_ip_supported(request):
add_floating_ip_info(request, loadbalancers)
return {'items': loadbalancers}
@rest_utils.ajax()
def post(self, request):
"""Create a new load balancer.
Creates a new load balancer as well as other optional resources such as
a listener, pool, monitor, etc.
"""
return create_loadbalancer(request)
@urls.register
class LoadBalancerStatusTree(generic.View):
"""API for retrieving the resource status tree for a single load balancer.
"""
url_regex = r'lbaas/loadbalancers/(?P[^/]+)/statuses/$'
@rest_utils.ajax()
def get(self, request, loadbalancer_id):
"""Get the status tree for a specific load balancer.
http://localhost/api/lbaas/loadbalancers/cc758c90-3d98-4ea1-af44-aab405c9c915/statuses
"""
return neutronclient(request).retrieve_loadbalancer_status(
loadbalancer_id)
@urls.register
class LoadBalancer(generic.View):
"""API for retrieving, updating, and deleting a single load balancer.
"""
url_regex = r'lbaas/loadbalancers/(?P[^/]+)/$'
@rest_utils.ajax()
def get(self, request, loadbalancer_id):
"""Get a specific load balancer.
http://localhost/api/lbaas/loadbalancers/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
loadbalancer = neutronclient(request).show_loadbalancer(
loadbalancer_id).get('loadbalancer')
if request.GET.get('full') and neutron.floating_ip_supported(request):
add_floating_ip_info(request, [loadbalancer])
return loadbalancer
@rest_utils.ajax()
def put(self, request, loadbalancer_id):
"""Edit a load balancer.
"""
kwargs = {'loadbalancer_id': loadbalancer_id}
update_loadbalancer(request, **kwargs)
@rest_utils.ajax()
def delete(self, request, loadbalancer_id):
"""Delete a specific load balancer.
http://localhost/api/lbaas/loadbalancers/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
neutronclient(request).delete_loadbalancer(loadbalancer_id)
@urls.register
class Listeners(generic.View):
"""API for load balancer listeners.
"""
url_regex = r'lbaas/listeners/$'
@rest_utils.ajax()
def get(self, request):
"""List of listeners for the current project.
The listing result is an object with property "items".
"""
loadbalancer_id = request.GET.get('loadbalancerId')
tenant_id = request.user.project_id
result = neutronclient(request).list_listeners(tenant_id=tenant_id)
listener_list = result.get('listeners')
if loadbalancer_id:
listener_list = self._filter_listeners(listener_list,
loadbalancer_id)
return {'items': listener_list}
@rest_utils.ajax()
def post(self, request):
"""Create a new listener.
Creates a new listener as well as other optional resources such as
a pool, members, and health monitor.
"""
kwargs = {'loadbalancer_id': request.DATA.get('loadbalancer_id')}
return create_listener(request, **kwargs)
def _filter_listeners(self, listener_list, loadbalancer_id):
filtered_listeners = []
for listener in listener_list:
if listener['loadbalancers'][0]['id'] == loadbalancer_id:
filtered_listeners.append(listener)
return filtered_listeners
@urls.register
class Listener(generic.View):
"""API for retrieving, updating, and deleting a single listener.
"""
url_regex = r'lbaas/listeners/(?P[^/]+)/$'
@rest_utils.ajax()
def get(self, request, listener_id):
"""Get a specific listener.
If the param 'includeChildResources' is passed in as a truthy value,
the details of all resources that exist under the listener will be
returned along with the listener details.
http://localhost/api/lbaas/listeners/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
listener = neutronclient(request).show_listener(
listener_id).get('listener')
if request.GET.get('includeChildResources'):
resources = {}
resources['listener'] = listener
if listener.get('default_pool_id'):
pool_id = listener['default_pool_id']
pool = neutronclient(request).show_lbaas_pool(
pool_id).get('pool')
resources['pool'] = pool
if pool.get('members'):
tenant_id = request.user.project_id
members = neutronclient(request).list_lbaas_members(
pool_id, tenant_id=tenant_id).get('members')
resources['members'] = members
if pool.get('healthmonitor_id'):
monitor_id = pool['healthmonitor_id']
monitor = neutronclient(request).show_lbaas_healthmonitor(
monitor_id).get('healthmonitor')
resources['monitor'] = monitor
return resources
else:
return listener
@rest_utils.ajax()
def put(self, request, listener_id):
"""Edit a listener as well as any resources below it.
"""
kwargs = {'listener_id': listener_id}
update_listener(request, **kwargs)
@rest_utils.ajax()
def delete(self, request, listener_id):
"""Delete a specific listener.
http://localhost/api/lbaas/listeners/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
neutronclient(request).delete_listener(listener_id)
@urls.register
class Pools(generic.View):
"""API for load balancer pools.
"""
url_regex = r'lbaas/pools/$'
@rest_utils.ajax()
def post(self, request):
"""Create a new pool.
Creates a new pool as well as other optional resources such as
members and health monitor.
"""
kwargs = {'loadbalancer_id': request.DATA.get('loadbalancer_id'),
'listener_id': request.DATA.get('parentResourceId')}
return create_pool(request, **kwargs)
@urls.register
class Pool(generic.View):
"""API for retrieving a single pool.
"""
url_regex = r'lbaas/pools/(?P[^/]+)/$'
@rest_utils.ajax()
def get(self, request, pool_id):
"""Get a specific pool.
If the param 'includeChildResources' is passed in as a truthy value,
the details of all resources that exist under the pool will be
returned along with the pool details.
http://localhost/api/lbaas/pools/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
pool = neutronclient(request).show_lbaas_pool(pool_id).get('pool')
if request.GET.get('includeChildResources'):
resources = {}
resources['pool'] = pool
if pool.get('members'):
tenant_id = request.user.project_id
members = neutronclient(request).list_lbaas_members(
pool_id, tenant_id=tenant_id).get('members')
resources['members'] = members
if pool.get('healthmonitor_id'):
monitor_id = pool['healthmonitor_id']
monitor = neutronclient(request).show_lbaas_healthmonitor(
monitor_id).get('healthmonitor')
resources['monitor'] = monitor
return resources
else:
return pool
@rest_utils.ajax()
def put(self, request, pool_id):
"""Edit a listener as well as any resources below it.
"""
kwargs = {'pool_id': pool_id}
update_pool(request, **kwargs)
@rest_utils.ajax()
def delete(self, request, pool_id):
"""Delete a specific pool.
http://localhost/api/lbaas/pools/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
neutronclient(request).delete_lbaas_pool(pool_id)
@urls.register
class Members(generic.View):
"""API for load balancer members.
"""
url_regex = r'lbaas/pools/(?P[^/]+)/members/$'
@rest_utils.ajax()
def get(self, request, pool_id):
"""List of members for the current project.
The listing result is an object with property "items".
"""
tenant_id = request.user.project_id
result = neutronclient(request).list_lbaas_members(pool_id,
tenant_id=tenant_id)
return {'items': result.get('members')}
@rest_utils.ajax()
def put(self, request, pool_id):
"""Update the list of members for the current project.
"""
# Assemble the lists of member id's to add and remove, if any exist
tenant_id = request.user.project_id
request_member_data = request.DATA.get('members', [])
existing_members = neutronclient(request).list_lbaas_members(
pool_id, tenant_id=tenant_id).get('members')
(members_to_add, members_to_delete) = get_members_to_add_remove(
request_member_data, existing_members)
if members_to_add or members_to_delete:
kwargs = {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete,
'pool_id': pool_id}
update_member_list(request, **kwargs)
@urls.register
class Member(generic.View):
"""API for retrieving a single member.
"""
url_regex = r'lbaas/pools/(?P[^/]+)' + \
'/members/(?P[^/]+)/$'
@rest_utils.ajax()
def get(self, request, member_id, pool_id):
"""Get a specific member belonging to a specific pool.
"""
return neutronclient(request).show_lbaas_member(
member_id, pool_id).get('member')
@rest_utils.ajax()
def put(self, request, member_id, pool_id):
"""Edit a pool member.
"""
data = request.DATA
spec = {
'weight': data['weight']
}
return neutronclient(request).update_lbaas_member(
member_id, pool_id, {'member': spec})
@urls.register
class HealthMonitors(generic.View):
"""API for load balancer pool health monitors.
"""
url_regex = r'lbaas/healthmonitors/$'
@rest_utils.ajax()
def post(self, request):
"""Create a new health monitor.
"""
kwargs = {'loadbalancer_id': request.DATA.get('loadbalancer_id'),
'pool_id': request.DATA.get('parentResourceId')}
return create_health_monitor(request, **kwargs)
@urls.register
class HealthMonitor(generic.View):
"""API for retrieving a single health monitor.
"""
url_regex = r'lbaas/healthmonitors/(?P[^/]+)/$'
@rest_utils.ajax()
def get(self, request, healthmonitor_id):
"""Get a specific health monitor.
"""
return neutronclient(request).show_lbaas_healthmonitor(
healthmonitor_id).get('healthmonitor')
@rest_utils.ajax()
def delete(self, request, healthmonitor_id):
"""Delete a specific health monitor.
http://localhost/api/lbaas/healthmonitors/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
neutronclient(request).delete_lbaas_healthmonitor(healthmonitor_id)
@rest_utils.ajax()
def put(self, request, healthmonitor_id):
"""Edit a health monitor.
"""
update_monitor(request)
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/api/rest/barbican.py 0000666 0001751 0001751 00000006664 13245511613 026761 0 ustar zuul zuul 0000000 0000000 # Copyright 2016 IBM Corp.
#
# 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.
"""API over the barbican service.
"""
from barbicanclient import client as barbican_client
from django.conf import settings
from django.views import generic
from keystoneclient.auth.identity import v2 as auth_v2
from keystoneclient.auth.identity import v3 as auth_v3
from keystoneclient import session
from horizon.utils.memoized import memoized # noqa
from openstack_dashboard.api import base
from openstack_dashboard.api import keystone
from openstack_dashboard.api.rest import urls
from openstack_dashboard.api.rest import utils as rest_utils
@memoized
def barbicanclient(request):
project_id = request.user.project_id
region = request.user.services_region
endpoint = base.url_for(request, 'key-manager')
if keystone.get_version() < 3:
auth = auth_v2.Token(settings.OPENSTACK_KEYSTONE_URL,
request.user.token.id,
tenant_id=project_id)
else:
domain_id = request.session.get('domain_context')
auth = auth_v3.Token(settings.OPENSTACK_KEYSTONE_URL,
request.user.token.id,
project_id=project_id,
project_domain_id=domain_id)
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
# If 'insecure' is True, 'verify' is False in all cases; otherwise
# pass the cacert path if it is present, or True if no cacert.
verify = not insecure and (cacert or True)
return barbican_client.Client(session=session.Session(auth=auth,
verify=verify),
endpoint=endpoint,
region_name=region)
@urls.register
class SSLCertificates(generic.View):
"""API for working with SSL certificate containers.
"""
url_regex = r'barbican/certificates/$'
@rest_utils.ajax()
def get(self, request):
"""List certificate containers.
The listing result is an object with property "items".
"""
limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
containers = barbicanclient(request).containers
params = {'limit': limit, 'type': 'certificate'}
result = containers._api.get('containers', params=params)
return {'items': result.get('containers')}
@urls.register
class Secrets(generic.View):
"""API for working with secrets.
"""
url_regex = r'barbican/secrets/$'
@rest_utils.ajax()
def get(self, request):
"""List secrets.
The listing result is an object with property "items".
"""
limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
secrets = barbicanclient(request).secrets
params = {'limit': limit}
result = secrets._api.get('secrets', params=params)
return {'items': result.get('secrets')}
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/ 0000775 0001751 0001751 00000000000 13245512321 025211 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ 0000775 0001751 0001751 00000000000 13245512321 026657 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/__init__.py 0000666 0001751 0001751 00000000000 13245511613 030763 0 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/ 0000775 0001751 0001751 00000000000 13245512321 032246 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/views.py 0000666 0001751 0001751 00000001431 13245511613 033761 0 ustar zuul zuul 0000000 0000000 # (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# 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 horizon.views import HorizonTemplateView
class IndexView(HorizonTemplateView):
template_name = 'project/ngloadbalancersv2/index.html'
page_title = 'Load Balancers'
././@LongLink 0000000 0000000 0000000 00000000146 00000000000 011216 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates0000775 0001751 0001751 00000000000 13245512321 034165 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000170 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates0000775 0001751 0001751 00000000000 13245512321 034165 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000202 00000000000 011207 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/index.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates0000666 0001751 0001751 00000000413 13245511613 034172 0 ustar zuul zuul 0000000 0000000 {% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Load Balancers" %}{% endblock %}
{% block page_header %}{% endblock %}
{% block ng_route_base %}
{% endblock %}
{% block main %}
{% endblock %}
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/urls.py 0000666 0001751 0001751 00000001441 13245511613 033612 0 ustar zuul zuul 0000000 0000000 # (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# 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 django.conf.urls import url
from neutron_lbaas_dashboard.dashboards.project.ngloadbalancersv2 import views
urlpatterns = [
url('', views.IndexView.as_view(), name='index'),
]
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/panel.py 0000666 0001751 0001751 00000003445 13245511613 033732 0 ustar zuul zuul 0000000 0000000 # (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# 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 oslo_log import log as logging
from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.api import neutron
LOG = logging.getLogger(__name__)
class NGLoadBalancers(horizon.Panel):
name = _("Load Balancers")
slug = 'ngloadbalancersv2'
permissions = ('openstack.services.network',)
def __init__(self):
LOG.warning('neutron-lbaas-dashboard is now deprecated. See: '
'https://wiki.openstack.org/wiki/Neutron/LBaaS/'
'Deprecation')
def allowed(self, context):
request = context['request']
try:
if not neutron.is_service_enabled(request,
config_name='enable_lb',
ext_name='lbaasv2'):
return False
except Exception:
LOG.error("Call to list enabled services failed. This is likely "
"due to a problem communicating with the Neutron "
"endpoint. Load Balancers v2 panel will not be "
"displayed")
return False
return super(NGLoadBalancers, self).allowed(context)
././@LongLink 0000000 0000000 0000000 00000000147 00000000000 011217 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/__init__.py neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/__init__.0000666 0001751 0001751 00000001277 13245511613 034022 0 ustar zuul zuul 0000000 0000000 # Copyright 2016 IBM Corp.
#
# 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.
# Register the REST API URLs so they can be called from the JavaScript files
from neutron_lbaas_dashboard.api import rest # noqa
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/dashboards/__init__.py 0000666 0001751 0001751 00000000000 13245511613 027315 0 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/ 0000775 0001751 0001751 00000000000 13245512321 024366 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/ 0000775 0001751 0001751 00000000000 13245512321 025146 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/ 0000775 0001751 0001751 00000000000 13245512321 026076 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/ 0000775 0001751 0001751 00000000000 13245512321 032272 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000157 00000000000 011220 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.0000666 0001751 0001751 00000035340 13245511613 033637 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.app.core.openstack-service-api')
.factory('horizon.app.core.openstack-service-api.lbaasv2', lbaasv2API);
lbaasv2API.$inject = [
'horizon.framework.util.http.service',
'horizon.framework.widgets.toast.service'
];
/**
* @ngdoc service
* @name horizon.app.core.openstack-service-api.loadbalancers
* @description Provides direct pass through to neutron LBaaS v2 with NO abstraction.
* @param apiService The horizon core API service.
* @param toastService The horizon toast service.
* @returns The LBaaS V2 service API.
*/
function lbaasv2API(apiService, toastService) {
var service = {
getLoadBalancers: getLoadBalancers,
getLoadBalancer: getLoadBalancer,
deleteLoadBalancer: deleteLoadBalancer,
createLoadBalancer: createLoadBalancer,
editLoadBalancer: editLoadBalancer,
getLoadBalancerStatusTree: getLoadBalancerStatusTree,
getListeners: getListeners,
getListener: getListener,
createListener: createListener,
editListener: editListener,
deleteListener: deleteListener,
getPool: getPool,
createPool: createPool,
editPool: editPool,
deletePool: deletePool,
getMembers: getMembers,
getMember: getMember,
editMember: editMember,
getHealthMonitor: getHealthMonitor,
deleteHealthMonitor: deleteHealthMonitor,
createHealthMonitor: createHealthMonitor,
editHealthMonitor: editHealthMonitor,
updateMemberList: updateMemberList
};
return service;
///////////////
// Load Balancers
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getLoadBalancers
* @description
* Get a list of load balancers.
* @param {boolean} full
* The listing result is an object with property "items". Each item is
* a load balancer.
*/
function getLoadBalancers(full) {
var params = { full: full };
return apiService.get('/api/lbaas/loadbalancers/', { params: params })
.error(function () {
toastService.add('error', gettext('Unable to retrieve load balancers.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getLoadBalancer
* @description
* Get a single load balancer by ID
* @param {string} id
* @param {boolean} full
* Specifies the id of the load balancer to request.
*/
function getLoadBalancer(id, full) {
var params = { full: full };
return apiService.get('/api/lbaas/loadbalancers/' + id + '/', { params: params })
.error(function () {
toastService.add('error', gettext('Unable to retrieve load balancer.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.deleteLoadBalancer
* @description
* Delete a single load balancer by ID
* @param {string} id
* @param {boolean} quiet
* Specifies the id of the load balancer to delete.
*/
function deleteLoadBalancer(id, quiet) {
var promise = apiService.delete('/api/lbaas/loadbalancers/' + id + '/');
return quiet ? promise : promise.error(function () {
toastService.add('error', gettext('Unable to delete load balancer.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.createLoadBalancer
* @description
* Create a new load balancer
* @param {object} spec
* Specifies the data used to create the new load balancer.
*/
function createLoadBalancer(spec) {
return apiService.post('/api/lbaas/loadbalancers/', spec)
.error(function () {
toastService.add('error', gettext('Unable to create load balancer.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.editLoadBalancer
* @description
* Edit a load balancer
* @param {string} id
* @param {object} spec
* Specifies the data used to update the load balancer.
*/
function editLoadBalancer(id, spec) {
return apiService.put('/api/lbaas/loadbalancers/' + id + '/', spec)
.error(function () {
toastService.add('error', gettext('Unable to update load balancer.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getLoadBalancerStatusTree
* @description
* Get the status tree for a load balancer
* @param {string} id
* Specifies the id of the load balancer to request the status tree for.
*/
function getLoadBalancerStatusTree(id) {
return apiService.get('/api/lbaas/loadbalancers/' + id + '/statuses/')
.error(function () {
toastService.add('error', gettext('Unable to retrieve load balancer status tree.'));
});
}
// Listeners
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getListeners
* @description
* Get the list of listeners.
* If a loadbalancer ID is passed as a parameter, the returning list of
* listeners will be filtered to include only those listeners under the
* specified loadbalancer.
* @param {string} id
* Specifies the id of the loadbalancer to request listeners for.
*
* The listing result is an object with property "items". Each item is
* a listener.
*/
function getListeners(id) {
var params = id ? {params: {loadbalancerId: id}} : {};
return apiService.get('/api/lbaas/listeners/', params)
.error(function () {
toastService.add('error', gettext('Unable to retrieve listeners.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getListener
* @description
* Get a single listener by ID.
* @param {string} id
* Specifies the id of the listener to request.
* @param {boolean} includeChildResources
* If truthy, all child resources below the listener will be included in the response.
*/
function getListener(id, includeChildResources) {
var params = includeChildResources
? {params: {includeChildResources: includeChildResources}}
: {};
return apiService.get('/api/lbaas/listeners/' + id + '/', params)
.error(function () {
toastService.add('error', gettext('Unable to retrieve listener.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.createListener
* @description
* Create a new listener
* @param {object} spec
* Specifies the data used to create the new listener.
*/
function createListener(spec) {
return apiService.post('/api/lbaas/listeners/', spec)
.error(function () {
toastService.add('error', gettext('Unable to create listener.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.editListener
* @description
* Edit a listener
* @param {string} id
* Specifies the id of the listener to update.
* @param {object} spec
* Specifies the data used to update the listener.
*/
function editListener(id, spec) {
return apiService.put('/api/lbaas/listeners/' + id + '/', spec)
.error(function () {
toastService.add('error', gettext('Unable to update listener.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.deleteListener
* @description
* Delete a single listener by ID
* @param {string} id
* @param {boolean} quiet
* Specifies the id of the listener to delete.
*/
function deleteListener(id, quiet) {
var promise = apiService.delete('/api/lbaas/listeners/' + id + '/');
return quiet ? promise : promise.error(function () {
toastService.add('error', gettext('Unable to delete listener.'));
});
}
// Pools
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getPool
* @description
* Get a single Pool by ID.
* @param {string} id
* Specifies the id of the pool to request.
* @param {boolean} includeChildResources
* If truthy, all child resources below the pool will be included in the response.
*/
function getPool(id, includeChildResources) {
var params = includeChildResources
? {params: {includeChildResources: includeChildResources}}
: {};
return apiService.get('/api/lbaas/pools/' + id + '/', params)
.error(function () {
toastService.add('error', gettext('Unable to retrieve pool.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.createPool
* @description
* Create a new pool
* @param {object} spec
* Specifies the data used to create the new pool.
*/
function createPool(spec) {
return apiService.post('/api/lbaas/pools/', spec)
.error(function () {
toastService.add('error', gettext('Unable to create pool.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.editPool
* @description
* Edit a pool
* @param {string} id
* Specifies the id of the pool to update.
* @param {object} spec
* Specifies the data used to update the pool.
*/
function editPool(id, spec) {
return apiService.put('/api/lbaas/pools/' + id + '/', spec)
.error(function () {
toastService.add('error', gettext('Unable to update pool.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.deletePool
* @description
* Delete a single pool by ID
* @param {string} id
* @param {boolean} quiet
* Specifies the id of the pool to delete.
*/
function deletePool(id, quiet) {
var promise = apiService.delete('/api/lbaas/pools/' + id + '/');
return quiet ? promise : promise.error(function () {
toastService.add('error', gettext('Unable to delete pool.'));
});
}
// Members
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getMembers
* @description
* Get a list of members.
* @param {string} poolId
* Specifies the id of the pool the members belong to.
*
* The listing result is an object with property "items". Each item is
* a member.
*/
function getMembers(poolId) {
return apiService.get('/api/lbaas/pools/' + poolId + '/members/')
.error(function () {
toastService.add('error', gettext('Unable to retrieve members.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getMember
* @description
* Get a single pool Member by ID.
* @param {string} poolId
* Specifies the id of the pool the member belongs to.
* @param {string} memberId
* Specifies the id of the member to request.
*/
function getMember(poolId, memberId) {
return apiService.get('/api/lbaas/pools/' + poolId + '/members/' + memberId + '/')
.error(function () {
toastService.add('error', gettext('Unable to retrieve member.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.editMember
* @description
* Edit a pool member.
* @param {string} id
* Specifies the id of the member to update.
* @param {object} spec
* Specifies the data used to update the member.
*/
function editMember(poolId, memberId, spec) {
return apiService.put('/api/lbaas/pools/' + poolId + '/members/' + memberId + '/', spec)
.error(function () {
toastService.add('error', gettext('Unable to update member.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.updateMemberList
* @description
* Update the list of pool members by adding or removing the necessary members.
* @param {string} poolId
* Specifies the id of the pool the members belong to.
* @param {object} spec
* Specifies the data used to update the member list.
*/
function updateMemberList(poolId, spec) {
return apiService.put('/api/lbaas/pools/' + poolId + '/members/', spec)
.error(function () {
toastService.add('error', gettext('Unable to update member list.'));
});
}
// Health Monitors
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getHealthMonitor
* @description
* Get a single pool health monitor by ID.
* @param {string} monitorId
* Specifies the id of the health monitor.
*/
function getHealthMonitor(monitorId) {
return apiService.get('/api/lbaas/healthmonitors/' + monitorId + '/')
.error(function () {
toastService.add('error', gettext('Unable to retrieve health monitor.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.editHealthMonitor
* @description
* Edit a health monitor
* @param {string} id
* Specifies the id of the health monitor to update.
* @param {object} spec
* Specifies the data used to update the health monitor.
*/
function editHealthMonitor(id, spec) {
return apiService.put('/api/lbaas/healthmonitors/' + id + '/', spec)
.error(function () {
toastService.add('error', gettext('Unable to update health monitor.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.deleteHealthMonitor
* @description
* Delete a single health monitor by ID
* @param {string} id
* @param {boolean} quiet
* Specifies the id of the health monitor to delete.
*/
function deleteHealthMonitor(id, quiet) {
var promise = apiService.delete('/api/lbaas/healthmonitors/' + id + '/');
return quiet ? promise : promise.error(function () {
toastService.add('error', gettext('Unable to delete health monitor.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.createHealthMonitor
* @description
* Create a new health monitor
* @param {object} spec
* Specifies the data used to create the new health monitor.
*/
function createHealthMonitor(spec) {
return apiService.post('/api/lbaas/healthmonitors/', spec)
.error(function () {
toastService.add('error', gettext('Unable to create health monitor.'));
});
}
}
}());
././@LongLink 0000000 0000000 0000000 00000000165 00000000000 011217 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican0000666 0001751 0001751 00000004363 13245511613 033771 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('Barbican API', function() {
var testCall, service;
var apiService = {};
var toastService = {};
beforeEach(module('horizon.mock.openstack-service-api', function($provide, initServices) {
testCall = initServices($provide, apiService, toastService);
}));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(inject(['horizon.app.core.openstack-service-api.barbican', function(barbicanAPI) {
service = barbicanAPI;
}]));
it('defines the service', function() {
expect(service).toBeDefined();
});
var tests = [
{
func: "getCertificates",
method: "get",
path: "/api/barbican/certificates/",
error: "Unable to retrieve SSL certificates."
},
{
func: "getSecrets",
method: "get",
path: "/api/barbican/secrets/",
error: "Unable to retrieve secrets."
}
];
// Iterate through the defined tests and apply as Jasmine specs.
angular.forEach(tests, function(params) {
it('defines the ' + params.func + ' call properly', function() {
var callParams = [apiService, service, toastService, params];
testCall.apply(this, callParams);
});
});
it('supresses the error if instructed for getCertificates', function() {
spyOn(apiService, 'get').and.returnValue("promise");
expect(service.getCertificates(true)).toBe("promise");
});
it('supresses the error if instructed for getSecrets', function() {
spyOn(apiService, 'get').and.returnValue("promise");
expect(service.getSecrets(true)).toBe("promise");
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000164 00000000000 011216 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.0000666 0001751 0001751 00000020347 13245511613 033640 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 API', function() {
var testCall, service;
var apiService = {};
var toastService = {};
beforeEach(module('horizon.mock.openstack-service-api', function($provide, initServices) {
testCall = initServices($provide, apiService, toastService);
}));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(inject(['horizon.app.core.openstack-service-api.lbaasv2', function(lbaasv2API) {
service = lbaasv2API;
}]));
it('defines the service', function() {
expect(service).toBeDefined();
});
var tests = [
{
func: 'getLoadBalancers',
method: 'get',
path: '/api/lbaas/loadbalancers/',
error: 'Unable to retrieve load balancers.',
testInput: [ true ],
data: { params: { full: true } }
},
{
func: 'getLoadBalancer',
method: 'get',
path: '/api/lbaas/loadbalancers/1234/',
error: 'Unable to retrieve load balancer.',
testInput: [ '1234', true ],
data: { params: { full: true } }
},
{
func: 'deleteLoadBalancer',
method: 'delete',
path: '/api/lbaas/loadbalancers/1234/',
error: 'Unable to delete load balancer.',
testInput: [ '1234' ]
},
{
func: 'getLoadBalancerStatusTree',
method: 'get',
path: '/api/lbaas/loadbalancers/1234/statuses/',
error: 'Unable to retrieve load balancer status tree.',
testInput: [ '1234' ]
},
{
func: 'getListeners',
method: 'get',
path: '/api/lbaas/listeners/',
error: 'Unable to retrieve listeners.',
testInput: [ '1234' ],
data: { params: { loadbalancerId: '1234' } }
},
{
func: 'getListeners',
method: 'get',
path: '/api/lbaas/listeners/',
data: {},
error: 'Unable to retrieve listeners.'
},
{
func: 'getListener',
method: 'get',
path: '/api/lbaas/listeners/1234/',
data: { params: { includeChildResources: true } },
error: 'Unable to retrieve listener.',
testInput: [ '1234', true ]
},
{
func: 'getListener',
method: 'get',
path: '/api/lbaas/listeners/1234/',
data: {},
error: 'Unable to retrieve listener.',
testInput: [ '1234', false ]
},
{
func: 'getPool',
method: 'get',
path: '/api/lbaas/pools/1234/',
data: { params: { includeChildResources: true } },
error: 'Unable to retrieve pool.',
testInput: [ '1234', true ]
},
{
func: 'getPool',
method: 'get',
path: '/api/lbaas/pools/1234/',
data: {},
error: 'Unable to retrieve pool.',
testInput: [ '1234', false ]
},
{
func: 'deletePool',
method: 'delete',
path: '/api/lbaas/pools/1234/',
error: 'Unable to delete pool.',
testInput: [ '1234' ]
},
{
func: 'getMembers',
method: 'get',
path: '/api/lbaas/pools/1234/members/',
error: 'Unable to retrieve members.',
testInput: [ '1234' ]
},
{
func: 'getMember',
method: 'get',
path: '/api/lbaas/pools/1234/members/5678/',
error: 'Unable to retrieve member.',
testInput: [ '1234', '5678' ]
},
{
func: 'editMember',
method: 'put',
path: '/api/lbaas/pools/1234/members/5678/',
error: 'Unable to update member.',
data: { weight: 2 },
testInput: [ '1234', '5678', { weight: 2 } ]
},
{
func: 'getHealthMonitor',
method: 'get',
path: '/api/lbaas/healthmonitors/1234/',
error: 'Unable to retrieve health monitor.',
testInput: [ '1234' ]
},
{
func: 'editHealthMonitor',
method: 'put',
path: '/api/lbaas/healthmonitors/1234/',
error: 'Unable to update health monitor.',
data: { name: 'healthmonitor-1' },
testInput: [ '1234', { name: 'healthmonitor-1' } ]
},
{
func: 'deleteHealthMonitor',
method: 'delete',
path: '/api/lbaas/healthmonitors/1234/',
error: 'Unable to delete health monitor.',
testInput: [ '1234' ]
},
{
func: 'createLoadBalancer',
method: 'post',
path: '/api/lbaas/loadbalancers/',
error: 'Unable to create load balancer.',
data: { name: 'loadbalancer-1' },
testInput: [ { name: 'loadbalancer-1' } ]
},
{
func: 'editLoadBalancer',
method: 'put',
path: '/api/lbaas/loadbalancers/1234/',
error: 'Unable to update load balancer.',
data: { name: 'loadbalancer-1' },
testInput: [ '1234', { name: 'loadbalancer-1' } ]
},
{
func: 'createListener',
method: 'post',
path: '/api/lbaas/listeners/',
error: 'Unable to create listener.',
data: { name: 'listener-1' },
testInput: [ { name: 'listener-1' } ]
},
{
func: 'editListener',
method: 'put',
path: '/api/lbaas/listeners/1234/',
error: 'Unable to update listener.',
data: { name: 'listener-1' },
testInput: [ '1234', { name: 'listener-1' } ]
},
{
func: 'deleteListener',
method: 'delete',
path: '/api/lbaas/listeners/1234/',
error: 'Unable to delete listener.',
testInput: [ '1234' ]
},
{
func: 'createPool',
method: 'post',
path: '/api/lbaas/pools/',
error: 'Unable to create pool.',
data: { name: 'pool-1' },
testInput: [ { name: 'pool-1' } ]
},
{
func: 'editPool',
method: 'put',
path: '/api/lbaas/pools/1234/',
error: 'Unable to update pool.',
data: { name: 'pool-1' },
testInput: [ '1234', { name: 'pool-1' } ]
},
{
func: 'createHealthMonitor',
method: 'post',
path: '/api/lbaas/healthmonitors/',
error: 'Unable to create health monitor.',
data: { name: 'healthmonitor-1' },
testInput: [ { name: 'healthmonitor-1' } ]
},
{
func: 'updateMemberList',
method: 'put',
path: '/api/lbaas/pools/1234/members/',
error: 'Unable to update member list.',
data: { name: 'member-1' },
testInput: [ '1234', { name: 'member-1' } ]
}
];
// Iterate through the defined tests and apply as Jasmine specs.
angular.forEach(tests, function(params) {
it('defines the ' + params.func + ' call properly', function() {
var callParams = [apiService, service, toastService, params];
testCall.apply(this, callParams);
});
});
it('supresses the error if instructed for deleteLoadBalancer', function() {
spyOn(apiService, 'delete').and.returnValue("promise");
expect(service.deleteLoadBalancer("whatever", true)).toBe("promise");
});
it('supresses the error if instructed for deleteListener', function() {
spyOn(apiService, 'delete').and.returnValue("promise");
expect(service.deleteListener("whatever", true)).toBe("promise");
});
it('supresses the error if instructed for deletePool', function() {
spyOn(apiService, 'delete').and.returnValue("promise");
expect(service.deletePool("whatever", true)).toBe("promise");
});
it('supresses the error if instructed for deleteHealthMonitor', function() {
spyOn(apiService, 'delete').and.returnValue("promise");
expect(service.deleteHealthMonitor("whatever", true)).toBe("promise");
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000160 00000000000 011212 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/app/core/openstack-service-api/barbican0000666 0001751 0001751 00000005004 13245511613 033762 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.app.core.openstack-service-api')
.factory('horizon.app.core.openstack-service-api.barbican', barbicanAPI);
barbicanAPI.$inject = [
'horizon.framework.util.http.service',
'horizon.framework.widgets.toast.service'
];
/**
* @ngdoc service
* @name horizon.app.core.openstack-service-api.barbican
* @description Provides direct pass through to barbican with NO abstraction.
* @param apiService The horizon core API service.
* @param toastService The horizon toast service.
* @returns The barbican service API.
*/
function barbicanAPI(apiService, toastService) {
var service = {
getCertificates: getCertificates,
getSecrets: getSecrets
};
return service;
///////////////
// SSL Certificate Containers
/**
* @name horizon.app.core.openstack-service-api.barbican.getCertificates
* @description
* Get a list of SSL certificate containers.
*
* @param {boolean} quiet
* The listing result is an object with property "items". Each item is
* a certificate container.
*/
function getCertificates(quiet) {
var promise = apiService.get('/api/barbican/certificates/');
return quiet ? promise : promise.error(function handleError() {
toastService.add('error', gettext('Unable to retrieve SSL certificates.'));
});
}
// Secrets
/**
* @name horizon.app.core.openstack-service-api.barbican.getSecrets
* @description
* Get a list of secrets.
*
* @param {boolean} quiet
* The listing result is an object with property "items". Each item is
* a secret.
*/
function getSecrets(quiet) {
var promise = apiService.get('/api/barbican/secrets/');
return quiet ? promise : promise.error(function handleError() {
toastService.add('error', gettext('Unable to retrieve secrets.'));
});
}
}
}());
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/ 0000775 0001751 0001751 00000000000 13245512321 026315 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/ 0000775 0001751 0001751 00000000000 13245512321 027763 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/ 0000775 0001751 0001751 00000000000 13245512321 031315 5 ustar zuul zuul 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/ 0000775 0001751 0001751 00000000000 13245512321 033167 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000156 00000000000 011217 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000775 0001751 0001751 00000000000 13245512321 034027 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000204 00000000000 011211 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.help.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000666 0001751 0001751 00000000777 13245511613 034051 0 ustar zuul zuul 0000000 0000000
The load balancer occupies a neutron network port and has an IP address assigned from a subnet.
IP address:
If an IP address is provided it must be a well-formed IPv4 or IPv6 address. The system will
attempt to assign the provided IP address to the load balancer. If an IP address is not provided
then one will be allocated for you.
Subnet:
The network on which to allocate the load balancer's IP address.
././@LongLink 0000000 0000000 0000000 00000000210 00000000000 011206 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.controller.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000666 0001751 0001751 00000003047 13245511613 034042 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2')
.controller('LoadBalancerDetailsController', LoadBalancerDetailsController);
LoadBalancerDetailsController.$inject = [
'horizon.dashboard.project.lbaasv2.patterns',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc controller
* @name LoadBalancerDetailsController
* @description
* The `LoadBalancerDetailsController` controller provides functions for
* configuring the load balancers step of the LBaaS wizard.
* @param patterns The LBaaS v2 patterns constant.
* @param gettext The horizon gettext function for translation.
* @returns undefined
*/
function LoadBalancerDetailsController(patterns, gettext) {
var ctrl = this;
// Error text for invalid fields
ctrl.ipError = gettext('The IP address is not valid.');
// IP address validation pattern
ctrl.ipPattern = [patterns.ipv4, patterns.ipv6].join('|');
}
})();
././@LongLink 0000000 0000000 0000000 00000000177 00000000000 011222 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000666 0001751 0001751 00000003754 13245511613 034047 0 ustar zuul zuul 0000000 0000000
Provide the details for the load balancer.
././@LongLink 0000000 0000000 0000000 00000000215 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/loadbalancer/loadbalancer.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/load0000666 0001751 0001751 00000002362 13245511613 034041 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('Load Balancer Details Step', function() {
beforeEach(module('horizon.framework.util.i18n'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
describe('LoadBalancerDetailsController', function() {
var ctrl;
beforeEach(inject(function($controller) {
ctrl = $controller('LoadBalancerDetailsController');
}));
it('should define error messages for invalid fields', function() {
expect(ctrl.ipError).toBeDefined();
});
it('should define patterns for field validation', function() {
expect(ctrl.ipPattern).toBeDefined();
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000161 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/modal.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moda0000666 0001751 0001751 00000005662 13245511613 034050 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2')
.factory('horizon.dashboard.project.lbaasv2.workflow.modal', modalService);
modalService.$inject = [
'$uibModal',
'horizon.framework.widgets.toast.service'
];
/**
* @ngdoc service
* @ngname horizon.dashboard.project.lbaasv2.workflow.modal
*
* @description
* Provides the service for opening the LBaaS create / edit modal.
*
* @param $uibModal The angular bootstrap $uibModal service.
* @param toastService The horizon toast service.
* @returns The modal service for the LBaaS workflow.
*/
function modalService($uibModal, toastService) {
var service = {
init: init
};
return service;
//////////////
/**
* @ngdoc method
* @name init
*
* @description
* Initialize a new scope for an LBaaS workflow modal.
*
* @param args An object containing the following properties:
* controller*: Controller to use for the wizard instance.
* message*: String to display using the toast service when wizard completes.
* allowed*: Function used to determine if the workflow action is allowed.
* handle: Function to call after the modal closes, receives the result of wizard submit.
* @returns An object with a single function 'open', used to open the modal.
*/
function init(args) {
return {
allowed: args.allowed,
perform: open
};
/**
* @ngdoc method
* @name open
*
* @description
* Open the modal.
*
* @param item The row item from the table action.
* @returns undefined
*/
function open(item) {
var spec = {
size: 'lg',
backdrop: 'static',
controller: 'ModalContainerController',
template: '',
windowClass: 'modal-dialog-wizard',
resolve: {
launchContext: function() {
return item;
}
}
};
$uibModal.open(spec).result.then(onModalClose);
}
function onModalClose(response) {
toastService.add('success', args.message);
if (args.handle) {
args.handle(response);
}
}
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000171 00000000000 011214 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/workflow.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/work0000666 0001751 0001751 00000006400 13245511613 034101 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 Workflow Service', function() {
var workflowService;
beforeEach(module('horizon.app.core'));
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.widgets.toast'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(inject(function ($injector) {
workflowService = $injector.get(
'horizon.dashboard.project.lbaasv2.workflow.workflow'
);
}));
it('should be defined', function () {
expect(workflowService).toBeDefined();
});
it('should have a title property', function () {
var workflow = workflowService('My Workflow');
expect(workflow.title).toBe('My Workflow');
});
it('should have default steps defined', function () {
var workflow = workflowService('My Workflow');
expect(workflow.steps).toBeDefined();
expect(workflow.steps.length).toBe(5);
var forms = [
'loadBalancerDetailsForm',
'listenerDetailsForm',
'poolDetailsForm',
'memberDetailsForm',
'monitorDetailsForm'
];
forms.forEach(function(expectedForm, idx) {
expect(workflow.steps[idx].formName).toBe(expectedForm);
});
});
it('should have a step for ssl certificates', function () {
var workflow = workflowService('My Workflow');
expect(workflow.certificatesStep).toBeDefined();
expect(workflow.certificatesStep.title).toBe('SSL Certificates');
});
it('can filter steps', function () {
var workflow = workflowService('My Workflow', 'foo', ['listener', 'pool']);
expect(workflow.steps).toBeDefined();
expect(workflow.steps.length).toBe(2);
expect(workflow.steps[0].checkReadiness).not.toBeDefined();
var forms = [
'listenerDetailsForm',
'poolDetailsForm'
];
forms.forEach(function(expectedForm, idx) {
expect(workflow.steps[idx].formName).toBe(expectedForm);
});
});
it('can wait for all steps to be ready', function () {
var workflow = workflowService('My Workflow', 'foo', null, 'promise');
expect(workflow.steps[0].checkReadiness).toBeDefined();
expect(workflow.steps[0].checkReadiness()).toBe('promise');
});
it('can be extended', function () {
var workflow = workflowService('My Workflow');
expect(workflow.append).toBeDefined();
expect(workflow.prepend).toBeDefined();
expect(workflow.after).toBeDefined();
expect(workflow.replace).toBeDefined();
expect(workflow.remove).toBeDefined();
expect(workflow.addController).toBeDefined();
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000156 00000000000 011217 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000775 0001751 0001751 00000000000 13245512321 034045 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000215 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000666 0001751 0001751 00000003723 13245511613 034061 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('SSL Certificates Step', function() {
var certs = [{
id: '1',
name: 'foo',
expiration: '2015-03-26T21:10:45.417835'
}];
beforeEach(module('horizon.framework.util.i18n'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
describe('CertificatesController', function() {
var ctrl, scope;
beforeEach(inject(function($controller) {
scope = {
model: {
spec: {
certificates: []
},
certificates: certs
}
};
ctrl = $controller('CertificatesController', { $scope: scope });
}));
it('should define transfer table properties', function() {
expect(ctrl.tableData).toBeDefined();
expect(ctrl.tableLimits).toBeDefined();
expect(ctrl.tableHelp).toBeDefined();
});
it('should have available certificates', function() {
expect(ctrl.tableData.available).toBeDefined();
expect(ctrl.tableData.available.length).toBe(1);
expect(ctrl.tableData.available[0].id).toBe('1');
});
it('should not have allocated members', function() {
expect(ctrl.tableData.allocated).toEqual([]);
});
it('should allow adding multiple certificates', function() {
expect(ctrl.tableLimits.maxAllocation).toBe(-1);
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000204 00000000000 011211 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.help.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000666 0001751 0001751 00000001412 13245511613 034052 0 ustar zuul zuul 0000000 0000000
If the listener uses the TERMINATED_HTTPS protocol, then one or more SSL certificates must
be selected. The first certificate will be the default.
Use the key-manager service to create any certificate containers before creating the listener.
The following documentation provides information on how to create a certificate container:
././@LongLink 0000000 0000000 0000000 00000000177 00000000000 011222 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000666 0001751 0001751 00000006234 13245511613 034061 0 ustar zuul zuul 0000000 0000000
Select one or more SSL certificates for the listener.
Certificate Name |
Expiration Date |
|
{$ ::trCtrl.helpText.noneAllocText $}
|
{$ ::row.name $} |
{$ row.expiration | date | noValue $} |
|
Certificate Name |
Expiration Date |
|
{$ ::trCtrl.helpText.noneAvailText $}
|
{$ ::row.name $} |
{$ row.expiration | date | noValue $} |
|
././@LongLink 0000000 0000000 0000000 00000000210 00000000000 011206 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/certificates/certificates.controller.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/cert0000666 0001751 0001751 00000003257 13245511613 034063 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2')
.controller('CertificatesController', CertificatesController);
CertificatesController.$inject = [
'$scope',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc controller
* @name CertificatesController
* @description
* The `CertificatesController` controller provides functions for adding certificates to a
* listener.
* @param $scope The angular scope object.
* @param gettext The horizon gettext function for translation.
* @returns undefined
*/
function CertificatesController($scope, gettext) {
var ctrl = this;
ctrl.tableData = {
available: $scope.model.certificates,
allocated: $scope.model.spec.certificates,
displayedAvailable: [],
displayedAllocated: []
};
ctrl.tableLimits = {
maxAllocation: -1
};
ctrl.tableHelp = {
availHelpText: '',
noneAllocText: gettext('Select certificates from the available certificates below'),
noneAvailText: gettext('No available certificates')
};
}
})();
././@LongLink 0000000 0000000 0000000 00000000151 00000000000 011212 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000775 0001751 0001751 00000000000 13245512321 034030 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000203 00000000000 011210 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000666 0001751 0001751 00000014065 13245511613 034045 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('Member Details Step', function() {
var model;
beforeEach(module('horizon.framework.util.i18n'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(function() {
model = {
spec: {
members: [],
pool: {
protocol: 'HTTP'
}
},
members: [{
id: '1',
name: 'foo',
description: 'bar',
weight: 1,
port: 80,
address: { ip: '1.2.3.4', subnet: '1' },
addresses: [{ ip: '1.2.3.4', subnet: '1' },
{ ip: '2.3.4.5', subnet: '2' }]
}],
subnets: [{
id: '1',
name: 'subnet-1'
}]
};
});
describe('MemberDetailsController', function() {
var ctrl;
beforeEach(inject(function($controller) {
ctrl = $controller('MemberDetailsController', { $scope: { model: model } });
}));
it('should define error messages for invalid fields', function() {
expect(ctrl.portError).toBeDefined();
expect(ctrl.weightError).toBeDefined();
expect(ctrl.ipError).toBeDefined();
});
it('should define patterns for validation', function() {
expect(ctrl.ipPattern).toBeDefined();
});
it('should define transfer table properties', function() {
expect(ctrl.tableData).toBeDefined();
expect(ctrl.tableLimits).toBeDefined();
expect(ctrl.tableHelp).toBeDefined();
});
it('should have available members', function() {
expect(ctrl.tableData.available).toBeDefined();
expect(ctrl.tableData.available.length).toBe(1);
expect(ctrl.tableData.available[0].id).toBe('1');
});
it('should not have allocated members', function() {
expect(ctrl.tableData.allocated).toEqual([]);
});
it('should allow adding multiple members', function() {
expect(ctrl.tableLimits.maxAllocation).toBe(-1);
});
it('should properly format address popover target', function() {
var target = ctrl.addressPopoverTarget(model.members[0]);
expect(target).toBe('1.2.3.4...');
});
it('should allocate a new external member', function() {
ctrl.allocateExternalMember();
expect(model.spec.members.length).toBe(1);
expect(model.spec.members[0].id).toBe(0);
expect(model.spec.members[0].address).toBeNull();
expect(model.spec.members[0].subnet).toBeNull();
});
it('should allocate a given member', function() {
ctrl.allocateMember(model.members[0]);
expect(model.spec.members.length).toBe(1);
expect(model.spec.members[0].id).toBe(0);
expect(model.spec.members[0].address).toEqual(model.members[0].address);
expect(model.spec.members[0].subnet).toBeUndefined();
expect(model.spec.members[0].port).toEqual(model.members[0].port);
});
it('should deallocate a given member', function() {
ctrl.deallocateMember(model.spec.members[0]);
expect(model.spec.members.length).toBe(0);
});
it('should show subnet name for available instance', function() {
var name = ctrl.getSubnetName(model.members[0]);
expect(name).toBe('subnet-1');
});
});
describe('Member Details Step Template', function() {
var $scope, $element, popoverContent;
beforeEach(module('templates'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(inject(function($injector) {
var $compile = $injector.get('$compile');
var $templateCache = $injector.get('$templateCache');
var basePath = $injector.get('horizon.dashboard.project.lbaasv2.basePath');
var popoverTemplates = $injector.get('horizon.dashboard.project.lbaasv2.popovers');
var markup = $templateCache.get(basePath + 'workflow/members/members.html');
$scope = $injector.get('$rootScope').$new();
$scope.model = model;
$element = $compile(markup)($scope);
var popoverScope = $injector.get('$rootScope').$new();
popoverScope.member = model.members[0];
popoverContent = $compile(popoverTemplates.ipAddresses)(popoverScope);
}));
it('should show IP addresses popover on hover', function() {
var ctrl = $element.scope().ctrl;
ctrl.tableData.displayedAvailable = model.members;
$scope.$apply();
var popoverElement = $element.find('span.addresses-popover');
expect(popoverElement.length).toBe(1);
$.fn.popover = angular.noop;
spyOn($.fn, 'popover');
spyOn(ctrl, 'showAddressPopover').and.callThrough();
popoverElement.trigger('mouseover');
expect(ctrl.showAddressPopover).toHaveBeenCalledWith(
jasmine.objectContaining({type: 'mouseover'}), model.members[0]);
expect($.fn.popover.calls.count()).toBe(2);
expect($.fn.popover.calls.argsFor(0)[0]).toEqual({
content: popoverContent,
html: true,
placement: 'top',
title: 'IP Addresses (2)'
});
expect($.fn.popover.calls.argsFor(1)[0]).toBe('show');
spyOn(ctrl, 'hideAddressPopover').and.callThrough();
popoverElement.trigger('mouseleave');
expect(ctrl.hideAddressPopover)
.toHaveBeenCalledWith(jasmine.objectContaining({type: 'mouseleave'}));
expect($.fn.popover.calls.count()).toBe(3);
expect($.fn.popover.calls.argsFor(2)[0]).toBe('hide');
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000176 00000000000 011221 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.controller.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000666 0001751 0001751 00000010624 13245511613 034042 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2')
.controller('MemberDetailsController', MemberDetailsController);
MemberDetailsController.$inject = [
'$scope',
'$compile',
'horizon.dashboard.project.lbaasv2.popovers',
'horizon.dashboard.project.lbaasv2.patterns',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc controller
* @name MemberDetailsController
* @description
* The `MemberDetailsController` controller provides functions for adding members to a pool.
* @param $scope The angular scope object.
* @param $compile The angular compile service.
* @param popoverTemplates LBaaS v2 popover templates constant.
* @param patterns The LBaaS v2 patterns constant.
* @param gettext The horizon gettext function for translation.
* @returns undefined
*/
function MemberDetailsController($scope, $compile, popoverTemplates, patterns, gettext) {
var ctrl = this;
var memberCounter = 0;
// Error text for invalid fields
ctrl.portError = gettext('The port must be a number between 1 and 65535.');
ctrl.weightError = gettext('The weight must be a number between 1 and 256.');
ctrl.ipError = gettext('The IP address is not valid.');
// Instances transer table widget properties
ctrl.tableData = {
available: $scope.model.members,
allocated: $scope.model.spec.members,
displayedAvailable: [],
displayedAllocated: []
};
ctrl.tableLimits = {
maxAllocation: -1
};
ctrl.tableHelp = {
availHelpText: '',
noneAllocText: gettext('No members have been allocated'),
noneAvailText: gettext('No available instances'),
allocTitle: gettext('Allocated Members'),
availTitle: gettext('Available Instances')
};
// IP address validation pattern
ctrl.ipPattern = [patterns.ipv4, patterns.ipv6].join('|');
// Functions to control the IP address popover
ctrl.showAddressPopover = showAddressPopover;
ctrl.hideAddressPopover = hideAddressPopover;
ctrl.addressPopoverTarget = addressPopoverTarget;
// Member management
ctrl.allocateExternalMember = allocateExternalMember;
ctrl.allocateMember = allocateMember;
ctrl.deallocateMember = deallocateMember;
ctrl.getSubnetName = getSubnetName;
//////////
function showAddressPopover(event, member) {
var element = angular.element(event.target);
var scope = $scope.$new(true);
scope.member = member;
element.popover({
content: $compile(popoverTemplates.ipAddresses)(scope),
html: true,
placement: 'top',
title: interpolate(gettext('IP Addresses (%(count)s)'),
{ count: member.addresses.length }, true)
});
element.popover('show');
}
function hideAddressPopover(event) {
var element = angular.element(event.target);
element.popover('hide');
}
function addressPopoverTarget(member) {
return interpolate(gettext('%(ip)s...'), { ip: member.address.ip }, true);
}
function allocateExternalMember() {
var protocol = $scope.model.spec.pool.protocol;
$scope.model.spec.members.push({
id: memberCounter++,
address: null,
subnet: null,
port: { HTTP: 80 }[protocol],
weight: 1
});
}
function allocateMember(member) {
var newMember = angular.extend(angular.copy(member), { id: memberCounter++ });
$scope.model.spec.members.push(newMember);
}
function deallocateMember(member) {
var index = $scope.model.spec.members.indexOf(member);
$scope.model.spec.members.splice(index, 1);
}
function getSubnetName(member) {
return $scope.model.subnets.filter(function filterSubnet(subnet) {
return subnet.id === member.address.subnet;
})[0].name;
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000165 00000000000 011217 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000666 0001751 0001751 00000017212 13245511613 034042 0 ustar zuul zuul 0000000 0000000
Add members to the load balancer pool.
Name |
IP Address |
|
{$ ::trCtrl.helpText.noneAvailText $}
|
{$ ::row.name $} |
{$ row.address.ip $}
{$ ctrl.addressPopoverTarget(row) $}
|
Add
|
././@LongLink 0000000 0000000 0000000 00000000172 00000000000 011215 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/members/members.help.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/memb0000666 0001751 0001751 00000002063 13245511613 034040 0 ustar zuul zuul 0000000 0000000
Members are the actual IP addresses that will receive traffic from the load balancer. Each
member must have a unique combination of IP address and port.
The Available Instances table contains existing compute instances that can be added as members
of the pool. Use the "Add external member" button to add a member not found in the Available
Instances table.
IP address:
The IP address of the member to receive traffic from the load balancer. Must be a well-formed
IPv4 or IPv6 address.
Subnet:
The network which contains the IP address of the member.
Port:
The port on which the member listens for traffic. Must be a number from 1 to 65535.
Weight:
The weight of a member determines the portion of requests or connections it services compared
to the other members of the pool. A higher weight means it will receive more traffic. Must be
a number from 1 to 256.
././@LongLink 0000000 0000000 0000000 00000000161 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/mode0000666 0001751 0001751 00000055152 13245511613 034053 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
var push = Array.prototype.push;
angular
.module('horizon.dashboard.project.lbaasv2')
.factory('horizon.dashboard.project.lbaasv2.workflow.model', workflowModel);
workflowModel.$inject = [
'$q',
'horizon.app.core.openstack-service-api.neutron',
'horizon.app.core.openstack-service-api.nova',
'horizon.app.core.openstack-service-api.lbaasv2',
'horizon.app.core.openstack-service-api.barbican',
'horizon.app.core.openstack-service-api.serviceCatalog',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc service
* @name horizon.dashboard.project.lbaasv2.workflow.model
*
* @description
* This is the M part of the MVC design pattern for the LBaaS wizard workflow. It is responsible
* for providing data to the view of each step in the workflow and collecting the user's input
* from the view. It is also the center point of communication between the UI and services API.
*
* @param $q The angular service for promises.
* @param neutronAPI The neutron service API.
* @param novaAPI The nova service API.
* @param lbaasv2API The LBaaS V2 service API.
* @param barbicanAPI The barbican service API.
* @param serviceCatalog The keystone service catalog API.
* @param gettext The horizon gettext function for translation.
* @returns The model service for the create load balancer workflow.
*/
function workflowModel(
$q,
neutronAPI,
novaAPI,
lbaasv2API,
barbicanAPI,
serviceCatalog,
gettext
) {
var ports, keymanagerPromise;
/**
* @ngdoc model api object
*/
var model = {
initializing: false,
initialized: false,
context: null,
/**
* @name spec
*
* @description
* A dictionary like object containing specification collected from user
* input.
*/
spec: null,
visibleResources: [],
subnets: [],
members: [],
listenerProtocols: ['HTTP', 'TCP', 'TERMINATED_HTTPS'],
methods: ['LEAST_CONNECTIONS', 'ROUND_ROBIN', 'SOURCE_IP'],
monitorTypes: ['HTTP', 'PING', 'TCP'],
monitorMethods: ['GET', 'HEAD'],
certificates: [],
listenerPorts: [],
/**
* api methods for UI controllers
*/
initialize: initialize,
submit: submit
};
return model;
///////////////
/**
* @ngdoc method
* @name workflowModel.initialize
* @returns {promise}
*
* @description
* Send request to get all data to initialize the model.
*
* @param resource Resource type being created / edited, one of 'loadbalancer', 'listener',
* 'pool', 'monitor', or 'members'.
* @param id ID of the resource being edited.
*/
function initialize(resource, id, loadBalancerId, parentResourceId) {
var promise;
model.certificatesError = false;
model.context = {
resource: resource,
id: id,
submit: null
};
model.visibleResources = [];
model.certificates = [];
model.listenerPorts = [];
model.spec = {
loadbalancer_id: loadBalancerId,
parentResourceId: parentResourceId,
loadbalancer: {
name: null,
description: null,
ip: null,
subnet: null
},
listener: {
id: null,
name: gettext('Listener 1'),
description: null,
protocol: null,
port: null
},
pool: {
id: null,
name: gettext('Pool 1'),
description: null,
protocol: null,
method: null
},
monitor: {
id: null,
type: null,
interval: 5,
retry: 3,
timeout: 5,
method: 'GET',
status: '200',
path: '/'
},
members: [],
certificates: []
};
if (!model.initializing) {
model.initializing = true;
promise = initializeResources();
}
return promise;
}
function initializeResources() {
var type = (model.context.id ? 'edit' : 'create') + model.context.resource;
keymanagerPromise = serviceCatalog.ifTypeEnabled('key-manager');
if (type === 'createloadbalancer' || model.context.resource === 'listener') {
keymanagerPromise.then(angular.noop, certificatesNotSupported);
}
var promise = {
createloadbalancer: initCreateLoadBalancer,
createlistener: initCreateListener,
createpool: initCreatePool,
createmonitor: initCreateMonitor,
createmembers: initUpdateMemberList,
editloadbalancer: initEditLoadBalancer,
editlistener: initEditListener,
editpool: initEditPool,
editmonitor: initEditMonitor
}[type](keymanagerPromise);
return promise.then(onInitSuccess, onInitFail);
}
function onInitSuccess() {
model.initializing = false;
model.initialized = true;
}
function onInitFail() {
model.initializing = false;
model.initialized = false;
}
function initCreateLoadBalancer(keymanagerPromise) {
model.context.submit = createLoadBalancer;
return $q.all([
lbaasv2API.getLoadBalancers().then(onGetLoadBalancers),
neutronAPI.getSubnets().then(onGetSubnets),
neutronAPI.getPorts().then(onGetPorts),
novaAPI.getServers().then(onGetServers),
keymanagerPromise.then(prepareCertificates, angular.noop)
]).then(initMemberAddresses);
}
function initCreateListener(keymanagerPromise) {
model.context.submit = createListener;
return $q.all([
lbaasv2API.getListeners(model.spec.loadbalancer_id).then(onGetListeners),
neutronAPI.getSubnets().then(onGetSubnets),
neutronAPI.getPorts().then(onGetPorts),
novaAPI.getServers().then(onGetServers),
keymanagerPromise.then(prepareCertificates, angular.noop)
]).then(initMemberAddresses);
}
function initCreatePool() {
model.context.submit = createPool;
// We get the listener details here because we need to know the listener protocol
// in order to default the new pool's protocol to match.
return $q.all([
lbaasv2API.getListener(model.spec.parentResourceId).then(onGetListener),
neutronAPI.getSubnets().then(onGetSubnets),
neutronAPI.getPorts().then(onGetPorts),
novaAPI.getServers().then(onGetServers)
]).then(initMemberAddresses);
}
function initCreateMonitor() {
model.context.submit = createHealthMonitor;
return $q.when();
}
function initUpdateMemberList() {
model.context.submit = updatePoolMemberList;
return $q.all([
lbaasv2API.getPool(model.spec.parentResourceId).then(onGetPool),
neutronAPI.getSubnets().then(onGetSubnets).then(getMembers).then(onGetMembers),
neutronAPI.getPorts().then(onGetPorts),
novaAPI.getServers().then(onGetServers)
]).then(initMemberAddresses);
}
function initEditLoadBalancer() {
model.context.submit = editLoadBalancer;
return $q.all([
lbaasv2API.getLoadBalancer(model.context.id).then(onGetLoadBalancer),
neutronAPI.getSubnets().then(onGetSubnets)
]).then(initSubnet);
}
function initEditListener() {
model.context.submit = editListener;
return $q.all([
neutronAPI.getSubnets().then(onGetSubnets).then(getListener).then(onGetListener),
neutronAPI.getPorts().then(onGetPorts),
novaAPI.getServers().then(onGetServers)
]).then(initMemberAddresses);
}
function initEditPool() {
model.context.submit = editPool;
return $q.all([
neutronAPI.getSubnets().then(onGetSubnets).then(getPool).then(onGetPool),
neutronAPI.getPorts().then(onGetPorts),
novaAPI.getServers().then(onGetServers)
]).then(initMemberAddresses);
}
function initEditMonitor() {
model.context.submit = editHealthMonitor;
return lbaasv2API.getHealthMonitor(model.context.id).then(onGetHealthMonitor);
}
/**
* @ngdoc method
* @name workflowModel.submit
* @returns {promise}
*
* @description
* Send request for completing the wizard.
*
* @returns Response from the LBaaS V2 API.
*/
function submit() {
var finalSpec = angular.copy(model.spec);
cleanFinalSpecLoadBalancer(finalSpec);
cleanFinalSpecListener(finalSpec);
cleanFinalSpecPool(finalSpec);
cleanFinalSpecMembers(finalSpec);
cleanFinalSpecMonitor(finalSpec);
removeNulls(finalSpec);
return model.context.submit(finalSpec);
}
function createLoadBalancer(spec) {
return lbaasv2API.createLoadBalancer(spec);
}
function createListener(spec) {
return lbaasv2API.createListener(spec);
}
function createPool(spec) {
return lbaasv2API.createPool(spec);
}
function createHealthMonitor(spec) {
return lbaasv2API.createHealthMonitor(spec);
}
function editLoadBalancer(spec) {
return lbaasv2API.editLoadBalancer(model.context.id, spec);
}
function editListener(spec) {
return lbaasv2API.editListener(model.context.id, spec);
}
function editPool(spec) {
return lbaasv2API.editPool(model.context.id, spec);
}
function editHealthMonitor(spec) {
return lbaasv2API.editHealthMonitor(model.context.id, spec);
}
function updatePoolMemberList(spec) {
return lbaasv2API.updateMemberList(model.spec.parentResourceId, spec);
}
function cleanFinalSpecLoadBalancer(finalSpec) {
var context = model.context;
// Load balancer requires subnet
if (!finalSpec.loadbalancer.subnet) {
delete finalSpec.loadbalancer;
} else {
finalSpec.loadbalancer.subnet = finalSpec.loadbalancer.subnet.id;
}
// Cannot edit the IP or subnet
if (context.resource === 'loadbalancer' && context.id) {
delete finalSpec.subnet;
delete finalSpec.ip;
}
}
function cleanFinalSpecListener(finalSpec) {
if (!finalSpec.listener.protocol || !finalSpec.listener.port) {
// Listener requires protocol and port
delete finalSpec.listener;
delete finalSpec.certificates;
} else if (finalSpec.listener.protocol !== 'TERMINATED_HTTPS') {
// Remove certificate containers if not using TERMINATED_HTTPS
delete finalSpec.certificates;
} else {
var containers = [];
angular.forEach(finalSpec.certificates, function(cert) {
containers.push(cert.id);
});
finalSpec.certificates = containers;
}
}
function cleanFinalSpecPool(finalSpec) {
// Pool requires method
if (!finalSpec.pool.method) {
delete finalSpec.pool;
} else {
// The pool protocol must be HTTP if the listener protocol is TERMINATED_HTTPS and
// otherwise has to match it.
var protocol = finalSpec.listener ? finalSpec.listener.protocol : finalSpec.pool.protocol;
finalSpec.pool.protocol = protocol === 'TERMINATED_HTTPS' ? 'HTTP' : protocol;
}
}
function cleanFinalSpecMembers(finalSpec) {
if (finalSpec.members.length === 0) {
delete finalSpec.members;
return;
}
var members = [];
angular.forEach(finalSpec.members, function cleanMember(member) {
if (member.address && member.port) {
var propsToRemove = ['name', 'description', 'addresses', 'allocatedMember'];
propsToRemove.forEach(function deleteProperty(prop) {
if (angular.isDefined(member[prop])) {
delete member[prop];
}
});
if (angular.isObject(member.address)) {
member.subnet = member.address.subnet;
member.address = member.address.ip;
} else if (member.subnet) {
member.subnet = member.subnet.id;
} else {
delete member.subnet;
}
members.push(member);
}
});
if (members.length > 0) {
finalSpec.members = members;
} else {
delete finalSpec.members;
}
}
function cleanFinalSpecMonitor(finalSpec) {
// Monitor requires an interval, retry count, and timeout
if (!angular.isNumber(finalSpec.monitor.interval) ||
!angular.isNumber(finalSpec.monitor.retry) ||
!angular.isNumber(finalSpec.monitor.timeout)) {
delete finalSpec.monitor;
return;
}
// Only include necessary monitor properties
if (finalSpec.monitor.type !== 'HTTP') {
delete finalSpec.monitor.method;
delete finalSpec.monitor.status;
delete finalSpec.monitor.path;
}
}
function removeNulls(finalSpec) {
angular.forEach(finalSpec, function deleteNullsForGroup(group, groupName) {
angular.forEach(group, function deleteNullValue(value, key) {
if (value === null) {
delete finalSpec[groupName][key];
}
});
});
}
function onGetLoadBalancers(response) {
var existingNames = {};
angular.forEach(response.data.items, function nameExists(lb) {
existingNames[lb.name] = 1;
});
var name;
var index = response.data.items.length;
do {
index += 1;
name = interpolate(gettext('Load Balancer %(index)s'), { index: index }, true);
} while (name in existingNames);
model.spec.loadbalancer.name = name;
}
function onGetListeners(response) {
var existingNames = {};
angular.forEach(response.data.items, function nameExists(listener) {
existingNames[listener.name] = 1;
model.listenerPorts.push(listener.protocol_port);
});
var name;
var index = response.data.items.length;
do {
index += 1;
name = interpolate(gettext('Listener %(index)s'), { index: index }, true);
} while (name in existingNames);
model.spec.listener.name = name;
}
function onGetSubnets(response) {
model.subnets.length = 0;
push.apply(model.subnets, response.data.items);
}
function onGetServers(response) {
model.members.length = 0;
var members = [];
angular.forEach(response.data.items, function addMember(server) {
// If the server is in a state where it does not have an IP address then we can't use it
if (server.addresses && !angular.equals({}, server.addresses)) {
members.push({
id: server.id,
name: server.name,
weight: 1
});
}
});
push.apply(model.members, members);
}
function onGetPorts(response) {
ports = response.data.items;
}
function onGetMembers(response) {
setMembersSpec(response.data.items);
}
function initMemberAddresses() {
angular.forEach(model.members, function initAddresses(member) {
var memberPorts = ports.filter(function filterPortByDevice(port) {
return port.device_id === member.id;
});
member.addresses = [];
angular.forEach(memberPorts, function addAddressesForPort(port) {
angular.forEach(port.fixed_ips, function addAddress(ip) {
member.addresses.push({
ip: ip.ip_address,
subnet: ip.subnet_id
});
});
});
member.address = member.addresses[0];
if (model.spec.pool.protocol) {
member.port = {HTTP: 80}[model.spec.pool.protocol];
}
});
}
function getListener() {
return lbaasv2API.getListener(model.context.id, true);
}
function getPool() {
return lbaasv2API.getPool(model.context.id, true);
}
function getMembers() {
return lbaasv2API.getMembers(model.spec.parentResourceId);
}
function onGetLoadBalancer(response) {
var loadbalancer = response.data;
setLoadBalancerSpec(loadbalancer);
}
function onGetListener(response) {
var result = response.data;
setListenerSpec(result.listener || result);
if (result.listener) {
model.visibleResources.push('listener');
model.spec.loadbalancer_id = result.listener.loadbalancers[0].id;
if (result.listener.protocol === 'TERMINATED_HTTPS') {
keymanagerPromise.then(prepareCertificates).then(function addAvailableCertificates() {
result.listener.sni_container_refs.forEach(function addAvailableCertificate(ref) {
model.certificates.filter(function matchCertificate(cert) {
return cert.id === ref;
}).forEach(function addCertificate(cert) {
model.spec.certificates.push(cert);
});
});
});
model.visibleResources.push('certificates');
}
}
if (result.pool) {
setPoolSpec(result.pool);
model.visibleResources.push('pool');
model.visibleResources.push('members');
if (result.members) {
setMembersSpec(result.members);
}
if (result.monitor) {
setMonitorSpec(result.monitor);
model.visibleResources.push('monitor');
}
}
}
function onGetPool(response) {
var result = response.data;
setPoolSpec(result.pool || result);
if (result.pool) {
model.visibleResources.push('pool');
model.visibleResources.push('members');
if (result.members) {
setMembersSpec(result.members);
}
if (result.monitor) {
setMonitorSpec(result.monitor);
model.visibleResources.push('monitor');
}
}
}
function setLoadBalancerSpec(loadbalancer) {
var spec = model.spec.loadbalancer;
spec.name = loadbalancer.name;
spec.description = loadbalancer.description;
spec.ip = loadbalancer.vip_address;
spec.subnet = loadbalancer.vip_subnet_id;
}
function setListenerSpec(listener) {
var spec = model.spec.listener;
spec.id = listener.id;
spec.name = listener.name;
spec.description = listener.description;
spec.protocol = listener.protocol;
spec.port = listener.protocol_port;
}
function setPoolSpec(pool) {
var spec = model.spec.pool;
spec.id = pool.id;
spec.name = pool.name;
spec.description = pool.description;
spec.protocol = pool.protocol;
spec.method = pool.lb_algorithm;
}
function setMembersSpec(membersList) {
model.spec.members.length = 0;
var members = [];
angular.forEach(membersList, function addMember(member) {
members.push({
id: member.id,
address: member.address,
subnet: mapSubnetObj(member.subnet_id),
port: member.protocol_port,
weight: member.weight,
allocatedMember: true
});
});
push.apply(model.spec.members, members);
}
function setMonitorSpec(monitor) {
var spec = model.spec.monitor;
spec.id = monitor.id;
spec.type = monitor.type;
spec.interval = monitor.delay;
spec.timeout = monitor.timeout;
spec.retry = monitor.max_retries;
spec.method = monitor.http_method;
spec.status = monitor.expected_codes;
spec.path = monitor.url_path;
}
function onGetHealthMonitor(response) {
setMonitorSpec(response.data);
}
function prepareCertificates() {
return $q.all([
barbicanAPI.getCertificates(true),
barbicanAPI.getSecrets(true)
]).then(onGetCertificates, certificatesError);
}
function onGetCertificates(results) {
// To use the TERMINATED_HTTPS protocol with a listener, the LBaaS v2 API wants a default
// container ref and a list of containers that hold TLS secrets. In barbican the container
// object has a list of references to the secrets it holds. This assumes that each
// certificate container has exactly one certificate and private key. We fetch both the
// certificate containers and the secrets so that we can display the secret names and
// expirations dates.
model.certificates.length = 0;
var certificates = [];
// Only accept containers that have both a certificate and private_key ref
var containers = results[0].data.items.filter(function validateContainer(container) {
container.refs = {};
container.secret_refs.forEach(function(ref) {
container.refs[ref.name] = ref.secret_ref;
});
return 'certificate' in container.refs && 'private_key' in container.refs;
});
var secrets = {};
results[1].data.items.forEach(function addSecret(secret) {
secrets[secret.secret_ref] = secret;
});
containers.forEach(function addCertificateContainer(container) {
var secret = secrets[container.refs.certificate];
certificates.push({
id: container.container_ref,
name: secret.name || secret.secret_ref.split('/').reverse()[0],
expiration: secret.expiration
});
});
push.apply(model.certificates, certificates);
}
function initSubnet() {
var subnet = model.subnets.filter(function filterSubnetsByLoadBalancer(s) {
return s.id === model.spec.loadbalancer.subnet;
})[0];
model.spec.loadbalancer.subnet = subnet;
}
function mapSubnetObj(subnetId) {
var subnet = model.subnets.filter(function mapSubnet(subnet) {
return subnet.id === subnetId;
});
return subnet[0];
}
function certificatesNotSupported() {
// This function is called if the key-manager service is not available. In that case we
// cannot support the TERMINATED_HTTPS listener protocol so we hide the option if creating
// a new load balancer or listener. However for editing we still need it.
if (!model.context.id) {
model.listenerProtocols.splice(2, 1);
}
}
function certificatesError() {
// This function is called if there is an error fetching the certificate containers or
// secrets. In that case we cannot support the TERMINATED_HTTPS listener protocol but we
// want to make the user aware of the error.
model.certificatesError = true;
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000151 00000000000 011212 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000775 0001751 0001751 00000000000 13245512321 034052 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000203 00000000000 011210 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000666 0001751 0001751 00000002730 13245511613 034063 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('Monitor Details Step', function() {
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
describe('MonitorDetailsController', function() {
var ctrl;
beforeEach(inject(function($controller) {
ctrl = $controller('MonitorDetailsController');
}));
it('should define error messages for invalid fields', function() {
expect(ctrl.intervalError).toBeDefined();
expect(ctrl.retryError).toBeDefined();
expect(ctrl.timeoutError).toBeDefined();
expect(ctrl.statusError).toBeDefined();
expect(ctrl.pathError).toBeDefined();
});
it('should define patterns for field validation', function() {
expect(ctrl.statusPattern).toBeDefined();
expect(ctrl.urlPathPattern).toBeDefined();
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000172 00000000000 011215 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.help.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000666 0001751 0001751 00000002356 13245511613 034067 0 ustar zuul zuul 0000000 0000000
The health monitor is used to determine the health of your pool members. Health checks
routinely run against each member within the pool and the result of the health check is used
to determine if the member receives new connections. Each pool can only have one health
monitor.
Interval:
The interval between health checks. Must be greater than or equal to the timeout.
Retries:
The number of allowed connection failures before marking the member as inactive. Must be a
number from 1 to 10.
Timeout:
The time after which a health check times out. Must be a number greater than or equal to 0
and less than or equal to the interval.
HTTP method:
The HTTP method used to perform the health check.
Expected status codes:
The expected HTTP status codes to get from a successful health check. Must be a single number,
a comma separated list of numbers, or a range (two numbers separated by a hyphen).
URL path:
The target of the health check HTTP request to the member. Must be a valid URL path.
././@LongLink 0000000 0000000 0000000 00000000176 00000000000 011221 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.controller.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000666 0001751 0001751 00000003736 13245511613 034072 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2')
.controller('MonitorDetailsController', MonitorDetailsController);
MonitorDetailsController.$inject = [
'horizon.dashboard.project.lbaasv2.patterns',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc controller
* @name MonitorDetailsController
* @description
* The `MonitorDetailsController` controller provides functions for
* configuring the health monitor step of the LBaaS wizard.
* @param patterns The LBaaS v2 patterns constant.
* @param gettext The horizon gettext function for translation.
* @returns undefined
*/
function MonitorDetailsController(patterns, gettext) {
var ctrl = this;
// Error text for invalid fields
/* eslint-disable max-len */
ctrl.intervalError = gettext('The health check interval must be greater than or equal to the timeout.');
/* eslint-enable max-len */
ctrl.retryError = gettext('The max retry count must be a number between 1 and 10.');
ctrl.timeoutError = gettext('The timeout must be a number greater than or equal to 0.');
ctrl.statusError = gettext('The expected status code is not valid.');
ctrl.pathError = gettext('The URL path is not valid.');
// HTTP status codes validation pattern
ctrl.statusPattern = patterns.httpStatusCodes;
ctrl.urlPathPattern = patterns.urlPath;
}
})();
././@LongLink 0000000 0000000 0000000 00000000165 00000000000 011217 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/monitor/monitor.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moni0000666 0001751 0001751 00000011305 13245511613 034061 0 ustar zuul zuul 0000000 0000000
Provide the details for the health monitor.
././@LongLink 0000000 0000000 0000000 00000000164 00000000000 011216 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/workflow.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/work0000666 0001751 0001751 00000007176 13245511613 034114 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2')
.factory('horizon.dashboard.project.lbaasv2.workflow.workflow', lbaasWorkflow);
lbaasWorkflow.$inject = [
'horizon.dashboard.project.lbaasv2.basePath',
'horizon.app.core.workflow.factory',
'horizon.framework.util.i18n.gettext'
];
function lbaasWorkflow(basePath, dashboardWorkflow, gettext) {
var workflowSteps = [
{
id: 'loadbalancer',
title: gettext('Load Balancer Details'),
templateUrl: basePath + 'workflow/loadbalancer/loadbalancer.html',
helpUrl: basePath + 'workflow/loadbalancer/loadbalancer.help.html',
formName: 'loadBalancerDetailsForm'
},
{
id: 'listener',
title: gettext('Listener Details'),
templateUrl: basePath + 'workflow/listener/listener.html',
helpUrl: basePath + 'workflow/listener/listener.help.html',
formName: 'listenerDetailsForm'
},
{
id: 'pool',
title: gettext('Pool Details'),
templateUrl: basePath + 'workflow/pool/pool.html',
helpUrl: basePath + 'workflow/pool/pool.help.html',
formName: 'poolDetailsForm'
},
{
id: 'members',
title: gettext('Pool Members'),
templateUrl: basePath + 'workflow/members/members.html',
helpUrl: basePath + 'workflow/members/members.help.html',
formName: 'memberDetailsForm'
},
{
id: 'monitor',
title: gettext('Monitor Details'),
templateUrl: basePath + 'workflow/monitor/monitor.html',
helpUrl: basePath + 'workflow/monitor/monitor.help.html',
formName: 'monitorDetailsForm'
}
];
// This step is kept separate from the rest because it is only added to the workflow by
// the Listener Details step if the TERMINATED_HTTPS protocol is selected.
var certificatesStep = {
id: 'certificates',
title: gettext('SSL Certificates'),
templateUrl: basePath + 'workflow/certificates/certificates.html',
helpUrl: basePath + 'workflow/certificates/certificates.help.html',
formName: 'certificateDetailsForm'
};
return initWorkflow;
function initWorkflow(title, icon, steps, promise) {
var filteredSteps = steps ? workflowSteps.filter(function(step) {
return steps.indexOf(step.id) > -1;
}) : workflowSteps;
// If a promise is provided then add a checkReadiness function to the first step so
// that the workflow will not show until the promise is resolved. There must always
// be at least one step in the workflow.
if (promise) {
filteredSteps[0] = angular.copy(filteredSteps[0]);
filteredSteps[0].checkReadiness = function() {
return promise;
};
}
return dashboardWorkflow({
title: title,
btnText: {
finish: title
},
btnIcon: {
finish: icon
},
steps: filteredSteps,
allSteps: workflowSteps,
certificatesStep: certificatesStep
});
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000152 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000775 0001751 0001751 00000000000 13245512321 034063 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000167 00000000000 011221 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000666 0001751 0001751 00000005223 13245511613 034074 0 ustar zuul zuul 0000000 0000000
Provide the details for the listener.
././@LongLink 0000000 0000000 0000000 00000000205 00000000000 011212 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000666 0001751 0001751 00000007620 13245511613 034077 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('Listener Details Step', function() {
beforeEach(module('horizon.framework.util.i18n'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
describe('ListenerDetailsController', function() {
var ctrl, workflow, listener, scope;
beforeEach(inject(function($controller) {
workflow = {
steps: [{ id: 'listener' }],
certificatesStep: { id: 'certificates' },
after: angular.noop,
remove: angular.noop
};
listener = {
protocol: null,
port: 80
};
scope = {
model: {
listenerPorts: [80],
members: [{port: ''}, {port: ''}],
spec: {
listener: listener,
members: [{port: ''}, {port: ''}]
}
},
workflow: workflow
};
ctrl = $controller('ListenerDetailsController', { $scope: scope });
}));
it('should define error messages for invalid fields', function() {
expect(ctrl.portNumberError).toBeDefined();
expect(ctrl.portUniqueError).toBeDefined();
});
it('should show certificates step if selecting TERMINATED_HTTPS', function() {
workflow.steps.push(workflow.certificatesStep);
spyOn(workflow, 'after');
ctrl.protocolChange('TERMINATED_HTTPS');
expect(workflow.after).not.toHaveBeenCalled();
workflow.steps.splice(1, 1);
ctrl.protocolChange('TERMINATED_HTTPS');
expect(workflow.after).toHaveBeenCalledWith('listener', workflow.certificatesStep);
});
it('should hide certificates step if not selecting TERMINATED_HTTPS', function() {
spyOn(workflow, 'remove');
ctrl.protocolChange('HTTP');
expect(workflow.remove).not.toHaveBeenCalled();
workflow.steps.push(workflow.certificatesStep);
ctrl.protocolChange('HTTP');
expect(workflow.remove).toHaveBeenCalledWith('certificates');
});
it('should update port on protocol change to HTTP', function() {
ctrl.protocolChange('HTTP');
expect(listener.port).toBe(81);
});
it('should update port on protocol change to TERMINATED_HTTPS', function() {
ctrl.protocolChange('TERMINATED_HTTPS');
expect(listener.port).toBe(443);
});
it('should update port on protocol change to TCP', function() {
ctrl.protocolChange('TCP');
expect(listener.port).toBeUndefined();
});
it('should update member ports on protocol change to TERMINATED_HTTPS', function() {
ctrl.protocolChange('TERMINATED_HTTPS');
scope.model.members.concat(scope.model.spec.members).forEach(function(member) {
expect(member.port).toBe(80);
});
});
it('should update member ports on protocol change to HTTP', function() {
ctrl.protocolChange('HTTP');
scope.model.members.concat(scope.model.spec.members).forEach(function(member) {
expect(member.port).toBe(80);
});
});
it('should update member ports on protocol change to TCP', function() {
ctrl.protocolChange('TCP');
scope.model.members.concat(scope.model.spec.members).forEach(function(member) {
expect(member.port).toBeUndefined();
});
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000174 00000000000 011217 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.help.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000666 0001751 0001751 00000001154 13245511613 034073 0 ustar zuul zuul 0000000 0000000
Each port that listens for traffic on a particular load balancer is configured separately and
tied to the load balancer. Multiple listeners can be associated with the same load balancer but
each must use a unique port.
Protocol:
The protocol for which the front end listens. The TERMINATED_HTTPS protocol is only available if
the key-manager service is enabled and you have authority to list certificate containers and
secrets.
Port:
The port on which the front end listens. Must be an integer from 1 to 65535.
././@LongLink 0000000 0000000 0000000 00000000200 00000000000 011205 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/listener/listener.controller.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/list0000666 0001751 0001751 00000005133 13245511613 034074 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2')
.controller('ListenerDetailsController', ListenerDetailsController);
ListenerDetailsController.$inject = [
'$scope',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc controller
* @name ListenerDetailsController
* @description
* The `ListenerDetailsController` controller provides functions for
* configuring the listener details step of the LBaaS wizard.
* @param $scope The angular scope object.
* @param gettext The horizon gettext function for translation.
* @returns undefined
*/
function ListenerDetailsController($scope, gettext) {
var ctrl = this;
ctrl.protocolChange = protocolChange;
// Error text for invalid fields
ctrl.portNumberError = gettext('The port must be a number between 1 and 65535.');
ctrl.portUniqueError = gettext(
'The port must be unique among all listeners attached to this load balancer.');
////////////
function protocolChange(protocol) {
var defaultPort = { HTTP: 80, TERMINATED_HTTPS: 443 }[protocol];
while (listenerPortExists(defaultPort)) {
defaultPort += 1;
}
$scope.model.spec.listener.port = defaultPort;
var members = $scope.model.members.concat($scope.model.spec.members);
members.forEach(function setMemberPort(member) {
member.port = { HTTP: 80, TERMINATED_HTTPS: 80 }[protocol];
});
var workflow = $scope.workflow;
var certificates = workflow.steps.some(function checkCertificatesStep(step) {
return step.id === 'certificates';
});
if (protocol === 'TERMINATED_HTTPS' && !certificates) {
workflow.after('listener', workflow.certificatesStep);
} else if (protocol !== 'TERMINATED_HTTPS' && certificates) {
workflow.remove('certificates');
}
}
function listenerPortExists(port) {
return $scope.model.listenerPorts.some(function(element) {
return element === port;
});
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000146 00000000000 011216 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool0000775 0001751 0001751 00000000000 13245512321 034061 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000157 00000000000 011220 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool0000666 0001751 0001751 00000002375 13245511613 034077 0 ustar zuul zuul 0000000 0000000
Provide the details for the pool.
././@LongLink 0000000 0000000 0000000 00000000164 00000000000 011216 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.help.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/pool0000666 0001751 0001751 00000001113 13245511613 034064 0 ustar zuul zuul 0000000 0000000
A pool represents a group of members over which the load balancing will be applied.
Method:
The load balancer algorithm that distributes traffic to the pool members.
-
LEAST_CONNECTIONS: Allocates requests to the instance with the least number of active
connections.
-
ROUND_ROBIN: Rotates requests evenly between multiple instances.
-
SOURCE_IP: Requests from a unique source IP address are consistently directed to the same instance.
././@LongLink 0000000 0000000 0000000 00000000166 00000000000 011220 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/modal.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/moda0000666 0001751 0001751 00000006324 13245511613 034044 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 Workflow Modal Service', function() {
var modalService, modal, response;
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.widgets.toast'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
response = {
data: {
id: '1'
}
};
modal = {
open: function() {
return {
result: {
then: function(func) {
func(response);
}
}
};
}
};
$provide.value('$uibModal', modal);
}));
beforeEach(inject(function ($injector) {
modalService = $injector.get('horizon.dashboard.project.lbaasv2.workflow.modal');
}));
it('should define an init function', function() {
expect(modalService.init).toBeDefined();
});
describe('modalService "perform" function tests', function() {
var toastService;
beforeEach(inject(function ($injector) {
toastService = $injector.get('horizon.framework.widgets.toast.service');
}));
it('calls modal.open', function() {
spyOn(modal, 'open').and.callThrough();
modalService.init({}).perform();
expect(modal.open).toHaveBeenCalled();
});
it('calls modal.open with expected values', function() {
spyOn(modal, 'open').and.callThrough();
modalService.init({}).perform();
var args = modal.open.calls.argsFor(0)[0];
expect(args.backdrop).toBe('static');
expect(args.controller).toBeDefined();
expect(args.resolve).toBeDefined();
expect(args.resolve.launchContext).toBeDefined();
});
it('launchContext function returns argument passed to open function', function() {
spyOn(modal, 'open').and.callThrough();
modalService.init({}).perform('foo');
var args = modal.open.calls.argsFor(0)[0];
expect(args.resolve.launchContext()).toBe('foo');
});
it('shows message upon success', function() {
spyOn(toastService, 'add').and.callThrough();
modalService.init({ message: 'foo' }).perform();
expect(toastService.add).toHaveBeenCalledWith('success', 'foo');
});
it('handles response upon success', function() {
spyOn(toastService, 'add').and.callThrough();
var args = { handle: angular.noop };
spyOn(args, 'handle');
modalService.init(args).perform();
expect(args.handle).toHaveBeenCalledWith(response);
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000166 00000000000 011220 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/workflow/mode0000666 0001751 0001751 00000222164 13245511613 034052 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 Workflow Model Service', function() {
var model, $q, scope, listenerResources, barbicanEnabled, certificatesError;
var includeChildResources = true;
beforeEach(module('horizon.framework.util.i18n'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(function() {
listenerResources = {
listener: {
id: '1234',
name: 'Listener 1',
description: 'listener description',
protocol: 'HTTP',
protocol_port: 80,
loadbalancers: [ { id: '1234' } ],
sni_container_refs: ['container2']
},
pool: {
id: '1234',
name: 'Pool 1',
protocol: 'HTTP',
lb_algorithm: 'ROUND_ROBIN',
description: 'pool description'
},
members: [
{
id: '1234',
address: '1.2.3.4',
subnet_id: 'subnet-1',
protocol_port: 80,
weight: 1
},
{
id: '5678',
address: '5.6.7.8',
subnet_id: 'subnet-1',
protocol_port: 80,
weight: 1
}
],
monitor: {
id: '1234',
type: 'HTTP',
delay: 1,
timeout: 1,
max_retries: 1,
http_method: 'POST',
expected_codes: '200',
url_path: '/test'
}
};
barbicanEnabled = true;
certificatesError = false;
});
beforeEach(module(function($provide) {
$provide.value('horizon.app.core.openstack-service-api.lbaasv2', {
getLoadBalancers: function() {
var loadbalancers = [
{ id: '1234', name: 'Load Balancer 1' },
{ id: '5678', name: 'Load Balancer 2' },
{ id: '9012', name: 'myLoadBalancer3' }
];
var deferred = $q.defer();
deferred.resolve({ data: { items: loadbalancers } });
return deferred.promise;
},
getLoadBalancer: function() {
var loadbalancer = {
id: '1234',
name: 'Load Balancer 1',
vip_address: '1.2.3.4',
vip_subnet_id: 'subnet-1',
description: ''
};
var deferred = $q.defer();
deferred.resolve({ data: loadbalancer });
return deferred.promise;
},
getListeners: function() {
var listeners = [
{ id: '1234', name: 'Listener 1', protocol_port: 80 },
{ id: '5678', name: 'Listener 2', protocol_port: 81 },
{ id: '9012', name: 'myListener3', protocol_port: 82 }
];
var deferred = $q.defer();
deferred.resolve({ data: { items: listeners } });
return deferred.promise;
},
getListener: function() {
var deferred = $q.defer();
var listenerData;
listenerData = includeChildResources ? listenerResources : listenerResources.listener;
deferred.resolve({ data: listenerData });
return deferred.promise;
},
getPool: function() {
var poolResources = angular.copy(listenerResources);
delete poolResources.listener;
var deferred = $q.defer();
var poolData;
poolData = includeChildResources ? poolResources : poolResources.pool;
deferred.resolve({ data: poolData });
return deferred.promise;
},
getMembers: function() {
var members = [
{
id: '1234',
address: '1.2.3.4',
subnet_id: 'subnet-1',
protocol_port: 80,
weight: 1
},
{
id: '5678',
address: '5.6.7.8',
subnet_id: 'subnet-1',
protocol_port: 80,
weight: 1
}];
var deferred = $q.defer();
deferred.resolve({ data: { items: members } });
return deferred.promise;
},
getHealthMonitor: function() {
var monitor = {
id: '1234',
type: 'HTTP',
delay: 1,
timeout: 1,
max_retries: 1,
http_method: 'POST',
expected_codes: '200',
url_path: '/test'
};
var deferred = $q.defer();
deferred.resolve({ data: monitor });
return deferred.promise;
},
createLoadBalancer: function(spec) {
return spec;
},
editLoadBalancer: function(id, spec) {
return spec;
},
createListener: function(spec) {
return spec;
},
editListener: function(id, spec) {
return spec;
},
createPool: function(spec) {
return spec;
},
editPool: function(id, spec) {
return spec;
},
createHealthMonitor: function(spec) {
return spec;
},
editHealthMonitor: function(id, spec) {
return spec;
},
updateMemberList: function(id, spec) {
return spec;
}
});
$provide.value('horizon.app.core.openstack-service-api.barbican', {
getCertificates: function() {
var containers = [
{
container_ref: 'container1',
secret_refs: [{name: 'certificate', secret_ref: 'secret1'}]
}, {
container_ref: 'container2',
secret_refs: [{name: 'certificate', secret_ref: 'certificate1'},
{name: 'private_key', secret_ref: 'privatekey1'}]
},
{
container_ref: 'container3',
secret_refs: [{name: 'certificate', secret_ref: 'certificate2'},
{name: 'private_key', secret_ref: 'privatekey2'}]
}
];
var deferred = $q.defer();
if (certificatesError) {
deferred.reject();
} else {
deferred.resolve({ data: { items: containers } });
}
return deferred.promise;
},
getSecrets: function() {
var secrets = [
{
name: 'foo',
expiration: '2016-03-26T21:10:45.417835',
secret_ref: 'certificate1'
},{
expiration: '2016-03-28T21:10:45.417835',
secret_ref: 'certificate2'
},{
secret_ref: 'privatekey1'
},{
secret_ref: 'privatekey2'
}
];
var deferred = $q.defer();
deferred.resolve({ data: { items: secrets } });
return deferred.promise;
}
});
$provide.value('horizon.app.core.openstack-service-api.neutron', {
getSubnets: function() {
var subnets = [ { id: 'subnet-1', name: 'subnet-1' },
{ id: 'subnet-2', name: 'subnet-2' } ];
var deferred = $q.defer();
deferred.resolve({ data: { items: subnets } });
return deferred.promise;
},
getPorts: function() {
var ports = [ { device_id: '1',
fixed_ips: [{ ip_address: '1.2.3.4', subnet_id: '1' },
{ ip_address: '2.3.4.5', subnet_id: '2' }] },
{ device_id: '2',
fixed_ips: [{ ip_address: '3.4.5.6', subnet_id: '1' },
{ ip_address: '4.5.6.7', subnet_id: '2' }] } ];
var deferred = $q.defer();
deferred.resolve({ data: { items: ports } });
return deferred.promise;
}
});
$provide.value('horizon.app.core.openstack-service-api.nova', {
getServers: function() {
var servers = [ { id: '1', name: 'server-1', addresses: { foo: 'bar' } },
{ id: '2', name: 'server-2', addresses: { foo: 'bar' } },
{ id: '3', name: 'server-3' }];
var deferred = $q.defer();
deferred.resolve({ data: { items: servers } });
return deferred.promise;
}
});
$provide.value('horizon.app.core.openstack-service-api.serviceCatalog', {
ifTypeEnabled: function() {
var deferred = $q.defer();
deferred[barbicanEnabled ? 'resolve' : 'reject']();
return deferred.promise;
}
});
}));
beforeEach(inject(function ($injector) {
model = $injector.get(
'horizon.dashboard.project.lbaasv2.workflow.model'
);
$q = $injector.get('$q');
scope = $injector.get('$rootScope').$new();
}));
describe('Initial model (pre-initialize)', function() {
it('is defined', function() {
expect(model).toBeDefined();
});
it('has initialization status parameters', function() {
expect(model.initializing).toBeDefined();
expect(model.initialized).toBeDefined();
});
it('does not yet have a spec', function() {
expect(model.spec).toBeNull();
});
it('has empty subnets array', function() {
expect(model.subnets).toEqual([]);
});
it('has empty members array', function() {
expect(model.members).toEqual([]);
});
it('has empty certificates array', function() {
expect(model.certificates).toEqual([]);
});
it('has empty listener ports array', function() {
expect(model.listenerPorts).toEqual([]);
});
it('has array of listener protocols', function() {
expect(model.listenerProtocols).toEqual(['HTTP', 'TCP', 'TERMINATED_HTTPS']);
});
it('has array of pool methods', function() {
expect(model.methods).toEqual(['LEAST_CONNECTIONS', 'ROUND_ROBIN', 'SOURCE_IP']);
});
it('has array of monitor types', function() {
expect(model.monitorTypes).toEqual(['HTTP', 'PING', 'TCP']);
});
it('has array of monitor methods', function() {
expect(model.monitorMethods).toEqual(['GET', 'HEAD']);
});
it('has an "initialize" function', function() {
expect(model.initialize).toBeDefined();
});
it('has a "submit" function', function() {
expect(model.submit).toBeDefined();
});
it('has a "context" object', function() {
expect(model.context).toBeDefined();
});
});
describe('Post initialize model (create loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(2);
expect(model.members.length).toBe(2);
expect(model.certificates.length).toBe(2);
expect(model.listenerPorts.length).toBe(0);
expect(model.spec).toBeDefined();
expect(model.spec.loadbalancer_id).toBeUndefined();
expect(model.spec.loadbalancer).toBeDefined();
expect(model.spec.listener).toBeDefined();
expect(model.spec.pool).toBeDefined();
expect(model.spec.members).toEqual([]);
expect(model.spec.certificates).toEqual([]);
expect(model.spec.monitor).toBeDefined();
expect(model.certificatesError).toBe(false);
});
it('should initialize names', function() {
expect(model.spec.loadbalancer.name).toBe('Load Balancer 4');
expect(model.spec.listener.name).toBe('Listener 1');
expect(model.spec.pool.name).toBe('Pool 1');
});
it('should initialize context properties', function() {
expect(model.context.resource).toBe('loadbalancer');
expect(model.context.id).toBeUndefined();
expect(model.context.submit).toBeDefined();
});
});
describe('Post initialize model (create listener)', function() {
beforeEach(function() {
model.initialize('listener', false, '1234');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(2);
expect(model.members.length).toBe(2);
expect(model.certificates.length).toBe(2);
expect(model.listenerPorts.length).toBe(3);
expect(model.spec).toBeDefined();
expect(model.spec.loadbalancer_id).toBe('1234');
expect(model.spec.loadbalancer).toBeDefined();
expect(model.spec.listener).toBeDefined();
expect(model.spec.pool).toBeDefined();
expect(model.spec.members).toEqual([]);
expect(model.spec.certificates).toEqual([]);
expect(model.spec.monitor).toBeDefined();
expect(model.certificatesError).toBe(false);
});
it('should initialize names', function() {
expect(model.spec.listener.name).toBe('Listener 4');
expect(model.spec.pool.name).toBe('Pool 1');
});
it('should initialize context properties', function() {
expect(model.context.resource).toBe('listener');
expect(model.context.id).toBeFalsy();
expect(model.context.submit).toBeDefined();
});
});
describe('Post initialize model (create pool)', function() {
beforeEach(function() {
includeChildResources = false;
model.initialize('pool', false, '1234', '5678');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(2);
expect(model.members.length).toBe(2);
expect(model.certificates.length).toBe(0);
expect(model.listenerPorts.length).toBe(0);
expect(model.spec).toBeDefined();
expect(model.spec.loadbalancer_id).toBe('1234');
expect(model.spec.parentResourceId).toBe('5678');
expect(model.spec.loadbalancer).toBeDefined();
expect(model.spec.listener).toBeDefined();
expect(model.spec.pool).toBeDefined();
expect(model.spec.members.length).toBe(0);
expect(model.spec.certificates).toEqual([]);
expect(model.spec.monitor).toBeDefined();
expect(model.certificatesError).toBe(false);
});
it('should initialize names', function() {
expect(model.spec.pool.name).toBe('Pool 1');
});
it('should initialize context properties', function() {
expect(model.context.resource).toBe('pool');
expect(model.context.id).toBeFalsy();
expect(model.context.submit).toBeDefined();
});
});
describe('Post initialize model (create health monitor)', function() {
beforeEach(function() {
model.initialize('monitor', null, 'loadbalancer1', 'pool1');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(0);
expect(model.members.length).toBe(0);
expect(model.certificates.length).toBe(0);
expect(model.listenerPorts.length).toBe(0);
expect(model.spec.loadbalancer_id).toBe('loadbalancer1');
expect(model.spec.parentResourceId).toBe('pool1');
expect(model.spec.members.length).toBe(0);
expect(model.spec.certificates).toEqual([]);
expect(model.certificatesError).toBe(false);
});
it('should initialize context properties', function() {
expect(model.context.resource).toBe('monitor');
expect(model.context.id).toBeFalsy();
expect(model.context.submit.name).toBe('createHealthMonitor');
});
});
describe('Post initialize model (edit loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer', '1234');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(2);
expect(model.members.length).toBe(0);
expect(model.certificates.length).toBe(0);
expect(model.listenerPorts.length).toBe(0);
expect(model.spec).toBeDefined();
expect(model.spec.loadbalancer_id).toBeUndefined();
expect(model.spec.loadbalancer).toBeDefined();
expect(model.spec.listener).toBeDefined();
expect(model.spec.pool).toBeDefined();
expect(model.spec.members).toEqual([]);
expect(model.spec.certificates).toEqual([]);
expect(model.spec.monitor).toBeDefined();
expect(model.certificatesError).toBe(false);
});
it('should initialize loadbalancer model spec properties', function() {
expect(model.spec.loadbalancer.name).toEqual('Load Balancer 1');
expect(model.spec.loadbalancer.description).toEqual('');
expect(model.spec.loadbalancer.ip).toEqual('1.2.3.4');
expect(model.spec.loadbalancer.subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
});
it('should not initialize listener model spec properties', function() {
expect(model.spec.listener.id).toBeNull();
expect(model.spec.listener.name).toBe('Listener 1');
expect(model.spec.listener.description).toBeNull();
expect(model.spec.listener.protocol).toBeNull();
expect(model.spec.listener.port).toBeNull();
});
it('should not initialize pool model spec properties', function() {
expect(model.spec.pool.id).toBeNull();
expect(model.spec.pool.name).toBe('Pool 1');
expect(model.spec.pool.description).toBeNull();
expect(model.spec.pool.protocol).toBeNull();
expect(model.spec.pool.method).toBeNull();
});
it('should initialize monitor model spec properties', function() {
expect(model.spec.monitor.type).toBeNull();
expect(model.spec.monitor.interval).toBe(5);
expect(model.spec.monitor.retry).toBe(3);
expect(model.spec.monitor.timeout).toBe(5);
expect(model.spec.monitor.method).toBe('GET');
expect(model.spec.monitor.status).toBe('200');
expect(model.spec.monitor.path).toBe('/');
});
it('should not initialize any members in the model spec', function() {
expect(model.spec.members).toEqual([]);
});
it('should initialize context', function() {
expect(model.context.resource).toBe('loadbalancer');
expect(model.context.id).toBe('1234');
expect(model.context.submit).toBeDefined();
});
it('should initialize listener protocols', function() {
expect(model.listenerProtocols.length).toBe(3);
expect(model.listenerProtocols.indexOf('TERMINATED_HTTPS')).toBe(2);
});
});
describe('Post initialize model (edit health monitor)', function() {
beforeEach(function() {
model.initialize('monitor', 'healthmonitor1');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(0);
expect(model.members.length).toBe(0);
expect(model.certificates.length).toBe(0);
expect(model.listenerPorts.length).toBe(0);
expect(model.spec.loadbalancer_id).toBeUndefined();
expect(model.spec.parentResourceId).toBeUndefined();
expect(model.spec.members.length).toBe(0);
expect(model.spec.certificates).toEqual([]);
expect(model.certificatesError).toBe(false);
expect(model.spec.monitor.id).toBe('1234');
expect(model.spec.monitor.type).toBe('HTTP');
expect(model.spec.monitor.interval).toBe(1);
expect(model.spec.monitor.timeout).toBe(1);
expect(model.spec.monitor.retry).toBe(1);
expect(model.spec.monitor.method).toBe('POST');
expect(model.spec.monitor.status).toBe('200');
expect(model.spec.monitor.path).toBe('/test');
});
it('should initialize context properties', function() {
expect(model.context.resource).toBe('monitor');
expect(model.context.id).toBe('healthmonitor1');
expect(model.context.submit.name).toBe('editHealthMonitor');
});
});
describe('Post initialize model (without barbican)', function() {
beforeEach(function() {
barbicanEnabled = false;
model.initialize('loadbalancer');
scope.$apply();
});
it('should initialize listener protocols', function() {
expect(model.listenerProtocols.length).toBe(2);
expect(model.listenerProtocols.indexOf('TERMINATED_HTTPS')).toBe(-1);
});
});
describe('Post initialize model (certificates error)', function() {
beforeEach(function() {
certificatesError = true;
model.initialize('loadbalancer');
scope.$apply();
});
it('should initialize listener protocols', function() {
expect(model.certificates).toEqual([]);
expect(model.certificatesError).toBe(true);
});
});
describe('Post initialize model (edit listener)', function() {
beforeEach(function() {
includeChildResources = true;
model.initialize('listener', '1234');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(2);
expect(model.members.length).toEqual(2);
expect(model.spec).toBeDefined();
expect(model.spec.loadbalancer_id).toBeDefined();
expect(model.spec.loadbalancer).toBeDefined();
expect(model.spec.listener).toBeDefined();
expect(model.spec.pool).toBeDefined();
expect(model.subnets.length).toBe(2);
expect(model.spec.monitor).toBeDefined();
});
it('should initialize the loadbalancer_id property', function() {
expect(model.spec.loadbalancer_id).toBe('1234');
});
it('should initialize all loadbalancer properties to null', function() {
expect(model.spec.loadbalancer.name).toBeNull();
expect(model.spec.loadbalancer.description).toBeNull();
expect(model.spec.loadbalancer.ip).toBeNull();
expect(model.spec.loadbalancer.subnet).toBeNull();
});
it('should initialize all listener properties', function() {
expect(model.spec.listener.id).toBe('1234');
expect(model.spec.listener.name).toBe('Listener 1');
expect(model.spec.listener.description).toBe('listener description');
expect(model.spec.listener.protocol).toBe('HTTP');
expect(model.spec.listener.port).toBe(80);
});
it('should initialize all pool properties', function() {
expect(model.spec.pool.id).toBe('1234');
expect(model.spec.pool.name).toBe('Pool 1');
expect(model.spec.pool.description).toBe('pool description');
expect(model.spec.pool.protocol).toBe('HTTP');
expect(model.spec.pool.method).toBe('ROUND_ROBIN');
});
it('should initialize all monitor properties', function() {
expect(model.spec.monitor.id).toBe('1234');
expect(model.spec.monitor.type).toBe('HTTP');
expect(model.spec.monitor.interval).toBe(1);
expect(model.spec.monitor.retry).toBe(1);
expect(model.spec.monitor.timeout).toBe(1);
expect(model.spec.monitor.method).toBe('POST');
expect(model.spec.monitor.status).toBe('200');
expect(model.spec.monitor.path).toBe('/test');
});
it('should initialize members and properties', function() {
expect(model.spec.members[0].id).toBe('1234');
expect(model.spec.members[0].address).toBe('1.2.3.4');
expect(model.spec.members[0].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
expect(model.spec.members[0].port).toBe(80);
expect(model.spec.members[0].weight).toBe(1);
expect(model.spec.members[1].id).toBe('5678');
expect(model.spec.members[1].address).toBe('5.6.7.8');
expect(model.spec.members[1].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
expect(model.spec.members[1].port).toBe(80);
expect(model.spec.members[1].weight).toBe(1);
});
it('should initialize context', function() {
expect(model.context.resource).toBe('listener');
expect(model.context.id).toBeDefined();
expect(model.context.submit).toBeDefined();
});
});
describe('Post initialize model (edit pool)', function() {
beforeEach(function() {
includeChildResources = true;
model.initialize('pool', '1234', 'loadbalancerId');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(2);
expect(model.members.length).toEqual(2);
expect(model.spec).toBeDefined();
expect(model.spec.loadbalancer_id).toBeDefined();
expect(model.spec.loadbalancer).toBeDefined();
expect(model.spec.listener).toBeDefined();
expect(model.spec.pool).toBeDefined();
expect(model.subnets.length).toBe(2);
expect(model.spec.monitor).toBeDefined();
});
it('should initialize the loadbalancer_id property', function() {
expect(model.spec.loadbalancer_id).toBe('loadbalancerId');
});
it('should initialize all loadbalancer properties to null', function() {
expect(model.spec.loadbalancer.name).toBeNull();
expect(model.spec.loadbalancer.description).toBeNull();
expect(model.spec.loadbalancer.ip).toBeNull();
expect(model.spec.loadbalancer.subnet).toBeNull();
});
it('should initialize all listener properties to null', function() {
expect(model.spec.listener.id).toBeNull();
expect(model.spec.listener.name).toBe('Listener 1');
expect(model.spec.listener.description).toBeNull();
expect(model.spec.listener.protocol).toBeNull();
expect(model.spec.listener.port).toBeNull();
});
it('should initialize all pool properties', function() {
expect(model.spec.pool.id).toBe('1234');
expect(model.spec.pool.name).toBe('Pool 1');
expect(model.spec.pool.description).toBe('pool description');
expect(model.spec.pool.protocol).toBe('HTTP');
expect(model.spec.pool.method).toBe('ROUND_ROBIN');
});
it('should initialize all monitor properties', function() {
expect(model.spec.monitor.id).toBe('1234');
expect(model.spec.monitor.type).toBe('HTTP');
expect(model.spec.monitor.interval).toBe(1);
expect(model.spec.monitor.retry).toBe(1);
expect(model.spec.monitor.timeout).toBe(1);
expect(model.spec.monitor.method).toBe('POST');
expect(model.spec.monitor.status).toBe('200');
expect(model.spec.monitor.path).toBe('/test');
});
it('should initialize members and properties', function() {
expect(model.spec.members[0].id).toBe('1234');
expect(model.spec.members[0].address).toBe('1.2.3.4');
expect(model.spec.members[0].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
expect(model.spec.members[0].port).toBe(80);
expect(model.spec.members[0].weight).toBe(1);
expect(model.spec.members[1].id).toBe('5678');
expect(model.spec.members[1].address).toBe('5.6.7.8');
expect(model.spec.members[1].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
expect(model.spec.members[1].port).toBe(80);
expect(model.spec.members[1].weight).toBe(1);
});
it('should initialize context', function() {
expect(model.context.resource).toBe('pool');
expect(model.context.id).toBeDefined();
expect(model.context.submit).toBeDefined();
});
});
describe('Post initialize model (update member list)', function() {
beforeEach(function() {
includeChildResources = false;
model.initialize('members', false, 'loadbalancerId', 'poolId');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(2);
expect(model.members.length).toEqual(2);
expect(model.spec).toBeDefined();
expect(model.spec.loadbalancer_id).toBeDefined();
expect(model.spec.loadbalancer).toBeDefined();
expect(model.spec.listener).toBeDefined();
expect(model.spec.pool).toBeDefined();
expect(model.subnets.length).toBe(2);
expect(model.spec.monitor).toBeDefined();
});
it('should initialize the loadbalancer_id property', function() {
expect(model.spec.loadbalancer_id).toBe('loadbalancerId');
});
it('should initialize all loadbalancer properties to null', function() {
expect(model.spec.loadbalancer.name).toBeNull();
expect(model.spec.loadbalancer.description).toBeNull();
expect(model.spec.loadbalancer.ip).toBeNull();
expect(model.spec.loadbalancer.subnet).toBeNull();
});
it('should initialize all listener properties to null', function() {
expect(model.spec.listener.id).toBeNull();
expect(model.spec.listener.name).toBe('Listener 1');
expect(model.spec.listener.description).toBeNull();
expect(model.spec.listener.protocol).toBeNull();
expect(model.spec.listener.port).toBeNull();
});
it('should initialize all pool properties', function() {
expect(model.spec.pool.id).toBe('1234');
expect(model.spec.pool.name).toBe('Pool 1');
expect(model.spec.pool.description).toBe('pool description');
expect(model.spec.pool.protocol).toBe('HTTP');
expect(model.spec.pool.method).toBe('ROUND_ROBIN');
});
it('should initialize all monitor properties to null', function() {
expect(model.spec.monitor.id).toBeNull();
expect(model.spec.monitor.type).toBeNull();
expect(model.spec.monitor.interval).toBe(5);
expect(model.spec.monitor.retry).toBe(3);
expect(model.spec.monitor.timeout).toBe(5);
expect(model.spec.monitor.method).toBe('GET');
expect(model.spec.monitor.status).toBe('200');
expect(model.spec.monitor.path).toBe('/');
});
it('should initialize members and properties', function() {
expect(model.spec.members[0].id).toBe('1234');
expect(model.spec.members[0].address).toBe('1.2.3.4');
expect(model.spec.members[0].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
expect(model.spec.members[0].port).toBe(80);
expect(model.spec.members[0].weight).toBe(1);
expect(model.spec.members[1].id).toBe('5678');
expect(model.spec.members[1].address).toBe('5.6.7.8');
expect(model.spec.members[1].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
expect(model.spec.members[1].port).toBe(80);
expect(model.spec.members[1].weight).toBe(1);
});
it('should initialize context', function() {
expect(model.context.resource).toBe('members');
expect(model.context.id).toBeFalsy();
expect(model.context.submit).toBeDefined();
});
});
describe('Post initialize model (edit listener TERMINATED_HTTPS)', function() {
beforeEach(function() {
includeChildResources = true;
listenerResources.listener.protocol = 'TERMINATED_HTTPS';
model.initialize('listener', '1234');
scope.$apply();
});
it('should initialize certificates', function() {
expect(model.certificates.length).toBe(2);
expect(model.spec.certificates.length).toBe(1);
expect(model.spec.certificates[0].id).toBe('container2');
});
});
describe('Post initialize model (edit listener TERMINATED_HTTPS no barbican)', function() {
beforeEach(function() {
listenerResources.listener.protocol = 'TERMINATED_HTTPS';
barbicanEnabled = false;
model.initialize('listener', '1234');
scope.$apply();
});
it('should initialize certificates', function() {
expect(model.certificates.length).toBe(0);
expect(model.spec.certificates.length).toBe(0);
expect(model.spec.listener.protocol).toBe('TERMINATED_HTTPS');
});
});
describe('Post initialize model - Initializing', function() {
beforeEach(function() {
model.initializing = true;
model.initialize('loadbalancer');
scope.$apply();
});
// This is here to ensure that as people add/change spec properties, they don't forget
// to implement tests for them.
it('has the right number of properties', function() {
expect(Object.keys(model.spec).length).toBe(8);
expect(Object.keys(model.spec.loadbalancer).length).toBe(4);
expect(Object.keys(model.spec.listener).length).toBe(5);
expect(Object.keys(model.spec.pool).length).toBe(5);
expect(Object.keys(model.spec.monitor).length).toBe(8);
expect(model.spec.members).toEqual([]);
});
it('sets load balancer ID to undefined', function() {
expect(model.spec.loadbalancer_id).toBeUndefined();
});
it('sets parent resource ID to undefined', function() {
expect(model.spec.parentResourceId).toBeUndefined();
});
it('sets load balancer name to null', function() {
expect(model.spec.loadbalancer.name).toBeNull();
});
it('sets load balancer description to null', function() {
expect(model.spec.loadbalancer.description).toBeNull();
});
it('sets load balancer ip address to null', function() {
expect(model.spec.loadbalancer.ip).toBeNull();
});
it('sets load balancer subnet to null', function() {
expect(model.spec.loadbalancer.subnet).toBeNull();
});
it('sets listener id to null', function() {
expect(model.spec.listener.id).toBeNull();
});
it('sets listener name to reasonable default', function() {
expect(model.spec.listener.name).toBe('Listener 1');
});
it('sets listener description to null', function() {
expect(model.spec.listener.description).toBeNull();
});
it('sets listener protocol to null', function() {
expect(model.spec.listener.protocol).toBeNull();
});
it('sets listener port to null', function() {
expect(model.spec.listener.port).toBeNull();
});
it('sets pool id to null', function() {
expect(model.spec.pool.id).toBeNull();
});
it('sets pool name to reasonable default', function() {
expect(model.spec.pool.name).toBe('Pool 1');
});
it('sets pool description to null', function() {
expect(model.spec.pool.description).toBeNull();
});
it('sets pool protocol to null', function() {
expect(model.spec.pool.protocol).toBeNull();
});
it('sets pool method to null', function() {
expect(model.spec.pool.method).toBeNull();
});
it('sets monitor id to null', function() {
expect(model.spec.monitor.id).toBeNull();
});
it('sets monitor type to null', function() {
expect(model.spec.monitor.type).toBeNull();
});
it('sets monitor interval to 5', function() {
expect(model.spec.monitor.interval).toBe(5);
});
it('sets monitor retry count to 3', function() {
expect(model.spec.monitor.retry).toBe(3);
});
it('sets monitor timeout to 5', function() {
expect(model.spec.monitor.timeout).toBe(5);
});
it('sets monitor method to default', function() {
expect(model.spec.monitor.method).toBe('GET');
});
it('sets monitor status code to default', function() {
expect(model.spec.monitor.status).toBe('200');
});
it('sets monitor URL path to default', function() {
expect(model.spec.monitor.path).toBe('/');
});
});
describe('Initialization failure', function() {
beforeEach(inject(function ($injector) {
var neutronAPI = $injector.get('horizon.app.core.openstack-service-api.neutron');
neutronAPI.getSubnets = function() {
var deferred = $q.defer();
deferred.reject('Error');
return deferred.promise;
};
}));
beforeEach(function() {
model.initialize('loadbalancer');
scope.$apply();
});
it('should fail to be initialized on subnets error', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(false);
expect(model.spec.loadbalancer.name).toBe('Load Balancer 4');
expect(model.subnets).toEqual([]);
});
});
describe('context (create loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('loadbalancer');
expect(model.context.id).toBeUndefined();
expect(model.context.submit.name).toBe('createLoadBalancer');
});
});
describe('context (edit loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer', '1');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('loadbalancer');
expect(model.context.id).toBe('1');
expect(model.context.submit.name).toBe('editLoadBalancer');
});
});
describe('context (create listener)', function() {
beforeEach(function() {
model.initialize('listener', false, '1234');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('listener');
expect(model.context.id).toBeFalsy();
expect(model.context.submit.name).toBe('createListener');
});
});
describe('context (edit listener)', function() {
beforeEach(function() {
includeChildResources = true;
model.initialize('listener', '1');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('listener');
expect(model.context.id).toBe('1');
expect(model.context.submit.name).toBe('editListener');
});
});
describe('context (create pool)', function() {
beforeEach(function() {
model.initialize('pool', false, '1234', '5678');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('pool');
expect(model.context.id).toBeFalsy();
expect(model.context.submit.name).toBe('createPool');
});
});
describe('context (edit pool)', function() {
beforeEach(function() {
includeChildResources = true;
model.initialize('pool', 'poolId', 'loadbalancerId');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('pool');
expect(model.context.id).toBe('poolId');
expect(model.context.submit.name).toBe('editPool');
});
});
describe('context (update member list)', function() {
beforeEach(function() {
model.initialize('members', false, 'loadbalancerId', 'poolId');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('members');
expect(model.context.id).toBeFalsy();
expect(model.context.submit.name).toBe('updatePoolMemberList');
});
});
describe('Model submit function (create loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer');
scope.$apply();
});
it('should set final spec properties', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'TCP';
model.spec.listener.port = 80;
model.spec.pool.name = 'pool name';
model.spec.pool.description = 'pool description';
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.members = [{
address: { ip: '1.2.3.4', subnet: '1' },
addresses: [{ ip: '1.2.3.4', subnet: '1' },
{ ip: '2.3.4.5', subnet: '2' }],
id: '1',
name: 'foo',
port: 80,
weight: 1
}, {
id: 'external-member-0',
address: '2.3.4.5',
subnet: null,
port: 80,
weight: 1
}, {
id: 'external-member-1',
address: null,
subnet: null,
port: 80,
weight: 1
}, {
id: 'external-member-2',
address: '3.4.5.6',
subnet: { id: '1' },
port: 80,
weight: 1
}];
model.spec.monitor.type = 'PING';
model.spec.monitor.interval = 1;
model.spec.monitor.retry = 1;
model.spec.monitor.timeout = 1;
model.spec.certificates = [{
id: 'container1',
name: 'foo',
expiration: '2015-03-26T21:10:45.417835'
}];
var finalSpec = model.submit();
expect(finalSpec.loadbalancer.name).toBe('Load Balancer 4');
expect(finalSpec.loadbalancer.description).toBeUndefined();
expect(finalSpec.loadbalancer.ip).toBe('1.2.3.4');
expect(finalSpec.loadbalancer.subnet).toBe(model.subnets[0].id);
expect(finalSpec.listener.name).toBe('Listener 1');
expect(finalSpec.listener.description).toBeUndefined();
expect(finalSpec.listener.protocol).toBe('TCP');
expect(finalSpec.listener.port).toBe(80);
expect(finalSpec.pool.name).toBe('pool name');
expect(finalSpec.pool.description).toBe('pool description');
expect(finalSpec.pool.protocol).toBe('TCP');
expect(finalSpec.pool.method).toBe('LEAST_CONNECTIONS');
expect(finalSpec.members.length).toBe(3);
expect(finalSpec.members[0].address).toBe('1.2.3.4');
expect(finalSpec.members[0].subnet).toBe('1');
expect(finalSpec.members[0].port).toBe(80);
expect(finalSpec.members[0].weight).toBe(1);
expect(finalSpec.members[0].id).toBe('1');
expect(finalSpec.members[0].addresses).toBeUndefined();
expect(finalSpec.members[0].name).toBeUndefined();
expect(finalSpec.members[0].allocatedMember).toBeUndefined();
expect(finalSpec.members[1].id).toBe('external-member-0');
expect(finalSpec.members[1].address).toBe('2.3.4.5');
expect(finalSpec.members[1].subnet).toBeUndefined();
expect(finalSpec.members[1].port).toBe(80);
expect(finalSpec.members[1].weight).toBe(1);
expect(finalSpec.members[1].allocatedMember).toBeUndefined();
expect(finalSpec.members[2].id).toBe('external-member-2');
expect(finalSpec.members[2].address).toBe('3.4.5.6');
expect(finalSpec.members[2].subnet).toBe('1');
expect(finalSpec.members[2].port).toBe(80);
expect(finalSpec.members[2].weight).toBe(1);
expect(finalSpec.members[2].allocatedMember).toBeUndefined();
expect(finalSpec.monitor.type).toBe('PING');
expect(finalSpec.monitor.interval).toBe(1);
expect(finalSpec.monitor.retry).toBe(1);
expect(finalSpec.monitor.timeout).toBe(1);
expect(finalSpec.certificates).toBeUndefined();
});
it('should set final spec certificates', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'TERMINATED_HTTPS';
model.spec.listener.port = 443;
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.certificates = [{
id: 'container1',
name: 'foo',
expiration: '2015-03-26T21:10:45.417835'
}];
var finalSpec = model.submit();
expect(finalSpec.loadbalancer.name).toBe('Load Balancer 4');
expect(finalSpec.loadbalancer.description).toBeUndefined();
expect(finalSpec.loadbalancer.ip).toBe('1.2.3.4');
expect(finalSpec.loadbalancer.subnet).toBe(model.subnets[0].id);
expect(finalSpec.listener.name).toBe('Listener 1');
expect(finalSpec.listener.description).toBeUndefined();
expect(finalSpec.listener.protocol).toBe('TERMINATED_HTTPS');
expect(finalSpec.listener.port).toBe(443);
expect(finalSpec.pool.protocol).toBe('HTTP');
expect(finalSpec.certificates).toEqual(['container1']);
});
it('should delete load balancer if any required property is not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeUndefined();
});
it('should delete listener if any required property is not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool).toBeUndefined();
});
it('should delete certificates if not using TERMINATED_HTTPS', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.certificates = [{id: '1'}];
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.certificates).toBeUndefined();
});
it('should delete pool if any required property is not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeUndefined();
});
it('should delete members if none selected', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
});
it('should delete members if no members are valid', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.members = [{
id: 'foo',
address: '2.3.4.5',
weight: 1
}];
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
});
it('should delete monitor if any required property not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.monitor.type = 'PING';
model.spec.monitor.interval = 1;
model.spec.monitor.retry = 1;
model.spec.monitor.timeout = null;
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
expect(finalSpec.monitor).toBeUndefined();
});
});
describe('Model submit function (edit loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer', '1234');
scope.$apply();
});
it('should set final spec properties', function() {
model.spec.loadbalancer.description = 'new description';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer.name).toBe('Load Balancer 1');
expect(finalSpec.loadbalancer.description).toBe('new description');
expect(finalSpec.loadbalancer.ip).toBe('1.2.3.4');
expect(finalSpec.loadbalancer.subnet).toBe('subnet-1');
});
});
describe('Model submit function (create listener)', function() {
beforeEach(function() {
model.initialize('listener', false, '1234');
scope.$apply();
});
it('should set final spec properties', function() {
model.spec.listener.protocol = 'TCP';
model.spec.listener.port = 80;
model.spec.pool.name = 'pool name';
model.spec.pool.description = 'pool description';
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.members = [{
address: { ip: '1.2.3.4', subnet: '1' },
addresses: [{ ip: '1.2.3.4', subnet: '1' },
{ ip: '2.3.4.5', subnet: '2' }],
id: '1',
name: 'foo',
port: 80,
weight: 1
}, {
id: 'external-member-0',
address: '2.3.4.5',
subnet: null,
port: 80,
weight: 1
}, {
id: 'external-member-1',
address: null,
subnet: null,
port: 80,
weight: 1
}, {
id: 'external-member-2',
address: '3.4.5.6',
subnet: { id: '1' },
port: 80,
weight: 1
}];
model.spec.monitor.type = 'PING';
model.spec.monitor.interval = 1;
model.spec.monitor.retry = 1;
model.spec.monitor.timeout = 1;
model.spec.certificates = [{
id: 'container1',
name: 'foo',
expiration: '2015-03-26T21:10:45.417835'
}];
var finalSpec = model.submit();
expect(finalSpec.listener.name).toBe('Listener 4');
expect(finalSpec.listener.description).toBeUndefined();
expect(finalSpec.listener.protocol).toBe('TCP');
expect(finalSpec.listener.port).toBe(80);
expect(finalSpec.pool.name).toBe('pool name');
expect(finalSpec.pool.description).toBe('pool description');
expect(finalSpec.pool.protocol).toBe('TCP');
expect(finalSpec.pool.method).toBe('LEAST_CONNECTIONS');
expect(finalSpec.members.length).toBe(3);
expect(finalSpec.members[0].address).toBe('1.2.3.4');
expect(finalSpec.members[0].subnet).toBe('1');
expect(finalSpec.members[0].port).toBe(80);
expect(finalSpec.members[0].weight).toBe(1);
expect(finalSpec.members[0].id).toBe('1');
expect(finalSpec.members[0].addresses).toBeUndefined();
expect(finalSpec.members[0].name).toBeUndefined();
expect(finalSpec.members[0].allocatedMember).toBeUndefined();
expect(finalSpec.members[1].id).toBe('external-member-0');
expect(finalSpec.members[1].address).toBe('2.3.4.5');
expect(finalSpec.members[1].subnet).toBeUndefined();
expect(finalSpec.members[1].port).toBe(80);
expect(finalSpec.members[1].weight).toBe(1);
expect(finalSpec.members[1].allocatedMember).toBeUndefined();
expect(finalSpec.members[2].id).toBe('external-member-2');
expect(finalSpec.members[2].address).toBe('3.4.5.6');
expect(finalSpec.members[2].subnet).toBe('1');
expect(finalSpec.members[2].port).toBe(80);
expect(finalSpec.members[2].weight).toBe(1);
expect(finalSpec.members[2].allocatedMember).toBeUndefined();
expect(finalSpec.monitor.type).toBe('PING');
expect(finalSpec.monitor.interval).toBe(1);
expect(finalSpec.monitor.retry).toBe(1);
expect(finalSpec.monitor.timeout).toBe(1);
expect(finalSpec.certificates).toBeUndefined();
});
it('should set final spec certificates', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'TERMINATED_HTTPS';
model.spec.listener.port = 443;
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.certificates = [{
id: 'container1',
name: 'foo',
expiration: '2015-03-26T21:10:45.417835'
}];
var finalSpec = model.submit();
expect(finalSpec.listener.name).toBe('Listener 4');
expect(finalSpec.listener.description).toBeUndefined();
expect(finalSpec.listener.protocol).toBe('TERMINATED_HTTPS');
expect(finalSpec.listener.port).toBe(443);
expect(finalSpec.pool.protocol).toBe('HTTP');
expect(finalSpec.certificates).toEqual(['container1']);
});
it('should delete listener if any required property is not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool).toBeUndefined();
});
it('should delete certificates if not using TERMINATED_HTTPS', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.certificates = [{id: '1'}];
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.certificates).toBeUndefined();
});
it('should delete pool if any required property is not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeUndefined();
});
it('should delete members if none selected', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
});
it('should delete members if no members are valid', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.members = [{
id: 'foo',
address: '2.3.4.5',
weight: 1
}];
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
});
it('should delete monitor if any required property not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.monitor.type = 'PING';
model.spec.monitor.interval = 1;
model.spec.monitor.retry = 1;
model.spec.monitor.timeout = null;
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
expect(finalSpec.monitor).toBeUndefined();
});
});
describe('Model submit function (create pool)', function() {
beforeEach(function() {
includeChildResources = false;
model.initialize('pool', false, '1234', '5678');
scope.$apply();
});
it('should set final spec properties', function() {
model.spec.listener.protocol = 'TCP';
model.spec.pool.name = 'pool name';
model.spec.pool.description = 'pool description';
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.members = [{
address: { ip: '1.2.3.4', subnet: '1' },
addresses: [{ ip: '1.2.3.4', subnet: '1' },
{ ip: '2.3.4.5', subnet: '2' }],
id: '1',
name: 'foo',
port: 80,
weight: 1
}, {
id: 'external-member-0',
address: '2.3.4.5',
subnet: null,
port: 80,
weight: 1
}, {
id: 'external-member-1',
address: null,
subnet: null,
port: 80,
weight: 1
}, {
id: 'external-member-2',
address: '3.4.5.6',
subnet: { id: '1' },
port: 80,
weight: 1
}];
model.spec.monitor.type = 'PING';
model.spec.monitor.interval = 1;
model.spec.monitor.retry = 1;
model.spec.monitor.timeout = 1;
model.spec.certificates = [{
id: 'container1',
name: 'foo',
expiration: '2015-03-26T21:10:45.417835'
}];
var finalSpec = model.submit();
expect(finalSpec.pool.name).toBe('pool name');
expect(finalSpec.pool.description).toBe('pool description');
expect(finalSpec.pool.protocol).toBe('TCP');
expect(finalSpec.pool.method).toBe('LEAST_CONNECTIONS');
expect(finalSpec.members.length).toBe(3);
expect(finalSpec.members[0].address).toBe('1.2.3.4');
expect(finalSpec.members[0].subnet).toBe('1');
expect(finalSpec.members[0].port).toBe(80);
expect(finalSpec.members[0].weight).toBe(1);
expect(finalSpec.members[0].id).toBe('1');
expect(finalSpec.members[0].addresses).toBeUndefined();
expect(finalSpec.members[0].name).toBeUndefined();
expect(finalSpec.members[0].allocatedMember).toBeUndefined();
expect(finalSpec.members[1].id).toBe('external-member-0');
expect(finalSpec.members[1].address).toBe('2.3.4.5');
expect(finalSpec.members[1].subnet).toBeUndefined();
expect(finalSpec.members[1].port).toBe(80);
expect(finalSpec.members[1].weight).toBe(1);
expect(finalSpec.members[1].allocatedMember).toBeUndefined();
expect(finalSpec.members[2].id).toBe('external-member-2');
expect(finalSpec.members[2].address).toBe('3.4.5.6');
expect(finalSpec.members[2].subnet).toBe('1');
expect(finalSpec.members[2].port).toBe(80);
expect(finalSpec.members[2].weight).toBe(1);
expect(finalSpec.members[2].allocatedMember).toBeUndefined();
expect(finalSpec.monitor.type).toBe('PING');
expect(finalSpec.monitor.interval).toBe(1);
expect(finalSpec.monitor.retry).toBe(1);
expect(finalSpec.monitor.timeout).toBe(1);
expect(finalSpec.certificates).toBeUndefined();
});
it('should delete listener if any required property is not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = '';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool).toBeUndefined();
});
it('should delete certificates if not using TERMINATED_HTTPS', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.certificates = [{id: '1'}];
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.certificates).toBeUndefined();
});
it('should delete pool if any required property is not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeUndefined();
});
it('should delete members if none selected', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
});
it('should delete members if no members are valid', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.members = [{
id: 'foo',
address: '2.3.4.5',
weight: 1
}];
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
});
it('should delete monitor if any required property not set', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.monitor.type = 'PING';
model.spec.monitor.interval = 1;
model.spec.monitor.retry = 1;
model.spec.monitor.timeout = null;
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeDefined();
expect(finalSpec.listener).toBeDefined();
expect(finalSpec.pool).toBeDefined();
expect(finalSpec.members).toBeUndefined();
expect(finalSpec.monitor).toBeUndefined();
});
});
describe('Model submit function (create health monitor)', function() {
beforeEach(function() {
model.initialize('monitor', null, 'loadbalancer1', 'pool1');
scope.$apply();
});
it('should set final spec properties', function() {
model.spec.monitor.type = 'HTTP';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer_id).toBe('loadbalancer1');
expect(finalSpec.parentResourceId).toBe('pool1');
expect(finalSpec.loadbalancer).toBeUndefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool).toBeUndefined();
expect(finalSpec.members).toBeUndefined();
expect(finalSpec.certificates).toBeUndefined();
expect(finalSpec.monitor.type).toBe('HTTP');
expect(finalSpec.monitor.interval).toBe(5);
expect(finalSpec.monitor.retry).toBe(3);
expect(finalSpec.monitor.timeout).toBe(5);
expect(finalSpec.monitor.method).toBe('GET');
expect(finalSpec.monitor.status).toBe('200');
expect(finalSpec.monitor.path).toBe('/');
});
});
describe('Model submit function (edit listener)', function() {
beforeEach(function() {
includeChildResources = true;
model.initialize('listener', '1234');
scope.$apply();
});
it('should set final spec properties', function() {
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeUndefined();
expect(finalSpec.listener.name).toBe('Listener 1');
expect(finalSpec.listener.description).toBe('listener description');
expect(finalSpec.listener.protocol).toBe('HTTP');
expect(finalSpec.listener.port).toBe(80);
expect(finalSpec.pool.name).toBe('Pool 1');
expect(finalSpec.pool.description).toBe('pool description');
expect(finalSpec.pool.protocol).toBe('HTTP');
expect(finalSpec.pool.method).toBe('ROUND_ROBIN');
expect(finalSpec.members.length).toBe(2);
expect(finalSpec.members[0].id).toBe('1234');
expect(finalSpec.members[0].address).toBe('1.2.3.4');
expect(finalSpec.members[0].subnet).toBe('subnet-1');
expect(finalSpec.members[0].port).toBe(80);
expect(finalSpec.members[0].weight).toBe(1);
expect(finalSpec.members[1].id).toBe('5678');
expect(finalSpec.members[1].address).toBe('5.6.7.8');
expect(finalSpec.members[1].subnet).toBe('subnet-1');
expect(finalSpec.members[1].port).toBe(80);
expect(finalSpec.members[1].weight).toBe(1);
expect(finalSpec.monitor.type).toBe('HTTP');
expect(finalSpec.monitor.interval).toBe(1);
expect(finalSpec.monitor.retry).toBe(1);
expect(finalSpec.monitor.timeout).toBe(1);
});
});
describe('Model submit function (edit pool)', function() {
beforeEach(function() {
includeChildResources = true;
model.initialize('pool', 'poolId', 'loadbalancerId');
scope.$apply();
});
it('should set final spec properties', function() {
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeUndefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool.name).toBe('Pool 1');
expect(finalSpec.pool.description).toBe('pool description');
expect(finalSpec.pool.protocol).toBe('HTTP');
expect(finalSpec.pool.method).toBe('ROUND_ROBIN');
expect(finalSpec.members.length).toBe(2);
expect(finalSpec.members[0].id).toBe('1234');
expect(finalSpec.members[0].address).toBe('1.2.3.4');
expect(finalSpec.members[0].subnet).toBe('subnet-1');
expect(finalSpec.members[0].port).toBe(80);
expect(finalSpec.members[0].weight).toBe(1);
expect(finalSpec.members[1].id).toBe('5678');
expect(finalSpec.members[1].address).toBe('5.6.7.8');
expect(finalSpec.members[1].subnet).toBe('subnet-1');
expect(finalSpec.members[1].port).toBe(80);
expect(finalSpec.members[1].weight).toBe(1);
expect(finalSpec.monitor.type).toBe('HTTP');
expect(finalSpec.monitor.interval).toBe(1);
expect(finalSpec.monitor.retry).toBe(1);
expect(finalSpec.monitor.timeout).toBe(1);
});
});
describe('Model submit function (update member list)', function() {
beforeEach(function() {
includeChildResources = false;
model.initialize('members', false, 'loadbalancerId', 'poolId');
scope.$apply();
});
it('should set final spec properties', function() {
var finalSpec = model.submit();
expect(finalSpec.loadbalancer_id).toBe('loadbalancerId');
expect(finalSpec.parentResourceId).toBe('poolId');
expect(finalSpec.loadbalancer).toBeUndefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool.name).toBe('Pool 1');
expect(finalSpec.pool.description).toBe('pool description');
expect(finalSpec.pool.protocol).toBe('HTTP');
expect(finalSpec.pool.method).toBe('ROUND_ROBIN');
expect(finalSpec.members.length).toBe(2);
expect(finalSpec.members[0].id).toBe('1234');
expect(finalSpec.members[0].address).toBe('1.2.3.4');
expect(finalSpec.members[0].subnet).toBe('subnet-1');
expect(finalSpec.members[0].port).toBe(80);
expect(finalSpec.members[0].weight).toBe(1);
expect(finalSpec.members[1].id).toBe('5678');
expect(finalSpec.members[1].address).toBe('5.6.7.8');
expect(finalSpec.members[1].subnet).toBe('subnet-1');
expect(finalSpec.members[1].port).toBe(80);
expect(finalSpec.members[1].weight).toBe(1);
expect(finalSpec.monitor.interval).toBe(5);
expect(finalSpec.monitor.retry).toBe(3);
expect(finalSpec.monitor.timeout).toBe(5);
});
});
describe('Model visible resources (edit pool, no pool in response)', function() {
beforeEach(function() {
includeChildResources = true;
delete listenerResources.pool;
model.initialize('pool', 'poolId', 'loadbalancerId');
scope.$apply();
});
it('should only show pool and monitor details', function() {
expect(model.visibleResources).toEqual([]);
});
});
describe('Model visible resources (edit pool, no existing members)', function() {
beforeEach(function() {
includeChildResources = true;
delete listenerResources.listener;
delete listenerResources.members;
model.initialize('pool', 'poolId', 'loadbalancerId');
scope.$apply();
});
it('should only show pool and monitor details', function() {
expect(model.visibleResources).toEqual(['pool', 'members', 'monitor']);
});
});
describe('Model visible resources (edit pool, no monitor)', function() {
beforeEach(function() {
includeChildResources = true;
delete listenerResources.listener;
delete listenerResources.monitor;
model.initialize('pool', 'poolId', 'loadbalancerId');
scope.$apply();
});
it('should only show pool and monitor details', function() {
expect(model.visibleResources).toEqual(['pool', 'members']);
});
});
describe('Model submit function (edit health monitor)', function() {
beforeEach(function() {
model.initialize('monitor', 'healthmonitor1');
scope.$apply();
});
it('should set final spec properties', function() {
model.spec.monitor.interval = 10;
model.spec.monitor.retry = 6;
model.spec.monitor.timeout = 8;
model.spec.monitor.method = 'GET';
model.spec.monitor.status = '200-204';
model.spec.monitor.path = '/foo/bar';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer_id).toBeUndefined();
expect(finalSpec.parentResourceId).toBeUndefined();
expect(finalSpec.loadbalancer).toBeUndefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool).toBeUndefined();
expect(finalSpec.members).toBeUndefined();
expect(finalSpec.certificates).toBeUndefined();
expect(finalSpec.monitor.type).toBe('HTTP');
expect(finalSpec.monitor.interval).toBe(10);
expect(finalSpec.monitor.retry).toBe(6);
expect(finalSpec.monitor.timeout).toBe(8);
expect(finalSpec.monitor.method).toBe('GET');
expect(finalSpec.monitor.status).toBe('200-204');
expect(finalSpec.monitor.path).toBe('/foo/bar');
});
});
describe('Model visible resources (edit listener, no pool)', function() {
beforeEach(function() {
delete listenerResources.pool;
model.initialize('listener', '1234');
scope.$apply();
});
it('should only show listener details', function() {
expect(model.visibleResources).toEqual(['listener']);
});
});
describe('Model visible resources (edit listener, no monitor or existing members)', function() {
beforeEach(function() {
delete listenerResources.members;
delete listenerResources.monitor;
model.initialize('listener', '1234');
scope.$apply();
});
it('should only show listener, pool, and member details', function() {
expect(model.visibleResources).toEqual(['listener', 'pool', 'members']);
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000151 00000000000 011212 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.modul0000666 0001751 0001751 00000010124 13245511613 033714 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2015 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
/**
* @ngdoc overview
* @name horizon.dashboard.project.lbaasv2
* @description
* The LBaaS v2 dashboard's top level module.
*/
angular
.module('horizon.dashboard.project.lbaasv2', [
'ngRoute',
'horizon.dashboard.project.lbaasv2.loadbalancers',
'horizon.dashboard.project.lbaasv2.listeners',
'horizon.dashboard.project.lbaasv2.pools',
'horizon.dashboard.project.lbaasv2.members',
'horizon.dashboard.project.lbaasv2.healthmonitors'
])
.config(config)
.constant('horizon.dashboard.project.lbaasv2.patterns', {
/* eslint-disable max-len */
ipv4: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$',
ipv6: '^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?$',
/* eslint-enable max-len */
// HTTP status codes - a single number, comma separated numbers, or a range of numbers.
httpStatusCodes: /^\d+((\s*-\s*\d+)|(\s*,\s*\d+)+)?$/,
// URL path - must start with "/" and can include anything after that
urlPath: /^((\/)|(\/[^/]+)+)$/
})
.constant('horizon.dashboard.project.lbaasv2.popovers', {
ipAddresses: ''
});
config.$inject = [
'$provide',
'$windowProvider',
'$routeProvider'
];
function config($provide, $windowProvider, $routeProvider) {
var basePath = $windowProvider.$get().STATIC_URL + 'dashboard/project/lbaasv2/';
$provide.constant('horizon.dashboard.project.lbaasv2.basePath', basePath);
var loadbalancers = '/project/ngloadbalancersv2';
var listener = loadbalancers + '/:loadbalancerId/listeners/:listenerId';
var pool = listener + '/pools/:poolId';
var member = pool + '/members/:memberId';
var healthmonitor = pool + '/healthmonitors/:healthmonitorId';
$routeProvider
.when(loadbalancers, {
templateUrl: basePath + 'loadbalancers/table.html'
})
.when(loadbalancers + '/:loadbalancerId', {
templateUrl: basePath + 'loadbalancers/detail.html'
})
.when(listener, {
templateUrl: basePath + 'listeners/detail.html'
})
.when(pool, {
templateUrl: basePath + 'pools/detail.html'
})
.when(member, {
templateUrl: basePath + 'members/detail.html'
})
.when(healthmonitor, {
templateUrl: basePath + 'healthmonitors/detail.html'
});
}
}());
neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/ 0000775 0001751 0001751 00000000000 13245512321 032747 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000150 00000000000 011211 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000775 0001751 0001751 00000000000 13245512321 033767 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000205 00000000000 011212 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/batch-actions.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000003775 13245511613 034012 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 Members Table Batch Actions Service', function() {
var actions;
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.widgets'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
var response = {
data: {
id: '1'
}
};
var modal = {
open: function() {
return {
result: {
then: function(func) {
func(response);
}
}
};
}
};
$provide.value('$uibModal', modal);
}));
beforeEach(inject(function ($injector) {
var batchActionsService = $injector.get(
'horizon.dashboard.project.lbaasv2.members.actions.batchActions');
actions = batchActionsService.actions();
}));
it('should define correct table batch actions', function() {
expect(actions.length).toBe(1);
expect(actions[0].template.text).toBe('Add/Remove Pool Members');
});
it('should have the "allowed" and "perform" functions', function() {
actions.forEach(function(action) {
expect(action.service.allowed).toBeDefined();
expect(action.service.perform).toBeDefined();
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000203 00000000000 011210 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/row-actions.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000003451 13245511613 034001 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 Members Row Actions Service', function() {
var actions;
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.widgets'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(inject(function ($injector) {
var rowActionsService = $injector.get(
'horizon.dashboard.project.lbaasv2.members.actions.rowActions');
actions = rowActionsService.init('1', '2').actions();
var loadbalancerService = $injector.get(
'horizon.dashboard.project.lbaasv2.loadbalancers.service');
spyOn(loadbalancerService, 'isActionable').and.returnValue(true);
}));
it('should define correct table row actions', function() {
expect(actions.length).toBe(1);
expect(actions[0].template.text).toBe('Update Weight');
});
it('should have the "allowed" and "perform" functions', function() {
actions.forEach(function(action) {
expect(action.service.allowed).toBeDefined();
expect(action.service.perform).toBeDefined();
});
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000176 00000000000 011221 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/row-actions.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000004016 13245511613 033777 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2.members')
.factory('horizon.dashboard.project.lbaasv2.members.actions.rowActions', rowActions);
rowActions.$inject = [
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
'horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service'
];
/**
* @ngdoc service
* @ngname horizon.dashboard.project.lbaasv2.members.actions.rowActions
*
* @description
* Provides the service for the pool members row actions.
*
* @param gettext The horizon gettext function for translation.
* @param loadBalancersService The LBaaS v2 load balancers service.
* @param editWeight The LBaaS v2 pool member edit weight service.
* @returns Members row actions service object.
*/
function rowActions(gettext, loadBalancersService, editWeight) {
var loadBalancerIsActionable, poolId;
var service = {
actions: actions,
init: init
};
return service;
///////////////
function init(loadbalancerId, _poolId_) {
loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId);
poolId = _poolId_;
return service;
}
function actions() {
return [{
service: editWeight.init(poolId, loadBalancerIsActionable),
template: {
text: gettext('Update Weight')
}
}];
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000200 00000000000 011205 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/batch-actions.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000004162 13245511613 034001 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2.members')
.factory('horizon.dashboard.project.lbaasv2.members.actions.batchActions',
tableBatchActions);
tableBatchActions.$inject = [
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
'horizon.dashboard.project.lbaasv2.members.actions.update-member-list'
];
/**
* @ngdoc service
* @ngname horizon.dashboard.project.lbaasv2.pools.actions.batchActions
*
* @description
* Provides the service for the Members table batch actions.
*
* @param gettext The horizon gettext function for translation.
* @param loadBalancersService The LBaaS v2 load balancers service.
* @param updateMemberListService The LBaaS v2 update member list service.
* @returns Members table batch actions service object.
*/
function tableBatchActions(
gettext, loadBalancersService, updateMemberListService
) {
var loadBalancerIsActionable, loadBalancerId;
var service = {
actions: actions,
init: init
};
return service;
///////////////
function init(_loadBalancerId_) {
loadBalancerId = _loadBalancerId_;
loadBalancerIsActionable = loadBalancersService.isActionable(loadBalancerId);
return service;
}
function actions() {
return [{
service: updateMemberListService.init(loadBalancerIsActionable).update,
template: {
text: gettext('Add/Remove Pool Members')
}
}];
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000164 00000000000 011216 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000775 0001751 0001751 00000000000 13245512321 033767 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000210 00000000000 011206 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/wizard.controller.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000002756 13245511613 034010 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2.members')
.controller('UpdateMemberListWizardController', UpdateMemberListWizardController);
UpdateMemberListWizardController.$inject = [
'$scope',
'$routeParams',
'horizon.dashboard.project.lbaasv2.workflow.model',
'horizon.dashboard.project.lbaasv2.workflow.workflow',
'horizon.framework.util.i18n.gettext'
];
function UpdateMemberListWizardController($scope, $routeParams, model, workflowService, gettext) {
var loadbalancerId = $routeParams.loadbalancerId;
var poolId = $routeParams.poolId;
var scope = $scope;
scope.model = model;
scope.submit = scope.model.submit;
scope.workflow = workflowService(
gettext('Add/Remove Pool Members'),
'fa fa-pencil',
['members']
);
scope.model.initialize('members', false, loadbalancerId, poolId);
}
})();
././@LongLink 0000000 0000000 0000000 00000000226 00000000000 011215 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/update-member-list.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000006354 13245511613 034006 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 Update Member List Action Service', function() {
var scope, $q, $route, policy, init, updateMemberListService, defer;
function allowed() {
spyOn(policy, 'ifAllowed').and.returnValue(true);
var promise = updateMemberListService.update.allowed();
var allowed;
promise.then(function() {
allowed = true;
}, function() {
allowed = false;
});
scope.$apply();
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_member_list']]});
return allowed;
}
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.widgets'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
var response = {
data: {
id: '9012'
}
};
var modal = {
open: function() {
return {
result: {
then: function(func) {
func(response);
}
}
};
}
};
$provide.value('$uibModal', modal);
}));
beforeEach(inject(function ($injector) {
scope = $injector.get('$rootScope').$new();
$q = $injector.get('$q');
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
$route = $injector.get('$route');
updateMemberListService = $injector.get(
'horizon.dashboard.project.lbaasv2.members.actions.update-member-list');
init = updateMemberListService.init;
defer = $q.defer();
}));
it('should define the correct service properties', function() {
expect(updateMemberListService.init).toBeDefined();
expect(updateMemberListService.update).toBeDefined();
});
it('should have the "allowed" and "perform" functions', function() {
expect(updateMemberListService.update.allowed).toBeDefined();
expect(updateMemberListService.update.perform).toBeDefined();
});
it('should allow editing a pool under an ACTIVE load balancer', function() {
defer.resolve();
init(defer.promise);
expect(allowed()).toBe(true);
});
it('should not allow editing a pool under an NON-ACTIVE load balancer', function() {
defer.reject();
init(defer.promise);
expect(allowed()).toBe(false);
});
it('should redirect after edit', function() {
spyOn($route, 'reload').and.callThrough();
updateMemberListService.update.perform();
expect($route.reload).toHaveBeenCalled();
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000221 00000000000 011210 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/update-member-list.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000004464 13245511613 034006 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2.members')
.factory('horizon.dashboard.project.lbaasv2.members.actions.update-member-list',
updateMemberListService);
updateMemberListService.$inject = [
'$q',
'$route',
'horizon.dashboard.project.lbaasv2.workflow.modal',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngDoc factory
* @name horizon.dashboard.project.lbaasv2.listeners.actions.updateMemberListService
* @description
* Provides the service for updating the list of pool members.
* @param $q The angular service for promises.
* @param $route The angular $route service.
* @param workflowModal The LBaaS workflow modal service.
* @param policy The horizon policy service.
* @param gettext The horizon gettext function for translation.
* @returns The load balancers members update member list service.
*/
function updateMemberListService(
$q, $route, workflowModal, policy, gettext
) {
var statePromise;
var updateList = workflowModal.init({
controller: 'UpdateMemberListWizardController',
message: gettext('The pool members have been updated.'),
handle: onUpdate,
allowed: allowed
});
var service = {
init: init,
update: updateList
};
return service;
//////////////
function init(_statePromise_) {
statePromise = _statePromise_;
return service;
}
function allowed(/*item*/) {
return $q.all([
statePromise,
policy.ifAllowed({ rules: [['neutron', 'update_member_list']] })
]);
}
function onUpdate(/*response*/) {
$route.reload();
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000215 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/update-list/wizard.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000004500 13245511613 033775 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
describe('LBaaS v2 Update Member List Wizard Controller', function() {
var ctrl, workflowSpy, scope;
var model = {
submit: function() {
return 'updated';
},
initialize: angular.noop
};
var workflow = 'foo';
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function ($provide) {
workflowSpy = jasmine.createSpy('workflow').and.returnValue(workflow);
$provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model);
$provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflowSpy);
}));
beforeEach(inject(function ($controller, $injector) {
scope = $injector.get('$rootScope').$new();
spyOn(model, 'initialize').and.callThrough();
ctrl = $controller('UpdateMemberListWizardController', {
$scope: scope,
$routeParams: {loadbalancerId: 'loadbalancerId',
poolId: 'poolId'}});
}));
it('defines the controller', function() {
expect(ctrl).toBeDefined();
});
it('calls initialize on the given model', function() {
expect(model.initialize).toHaveBeenCalledWith('members', false, 'loadbalancerId', 'poolId');
});
it('sets scope.workflow to the given workflow', function() {
expect(scope.workflow).toBe(workflow);
});
it('initializes workflow with correct properties', function() {
expect(workflowSpy).toHaveBeenCalledWith('Add/Remove Pool Members',
'fa fa-pencil', ['members']);
});
it('defines scope.submit', function() {
expect(scope.submit).toBe(model.submit);
expect(scope.submit()).toBe('updated');
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000164 00000000000 011216 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/ neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000775 0001751 0001751 00000000000 13245512321 033767 5 ustar zuul zuul 0000000 0000000 ././@LongLink 0000000 0000000 0000000 00000000204 00000000000 011211 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.service.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000006271 13245511613 034004 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2.members')
.factory('horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service',
modalService);
modalService.$inject = [
'$q',
'$uibModal',
'$route',
'horizon.dashboard.project.lbaasv2.basePath',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.widgets.toast.service',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc service
* @ngname horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service
*
* @description
* Provides the service for the pool member Edit Weight action.
*
* @param $q The angular service for promises.
* @param $uibModal The angular bootstrap $uibModal service.
* @param $route The angular $route service.
* @param basePath The LBaaS v2 module base path.
* @param policy The horizon policy service.
* @param toastService The horizon toast service.
* @param gettext The horizon gettext function for translation.
*
* @returns The Edit Weight modal service.
*/
function modalService(
$q,
$uibModal,
$route,
basePath,
policy,
toastService,
gettext
) {
var poolId, statePromise;
var service = {
perform: open,
allowed: allowed,
init: init
};
return service;
////////////
function init(_poolId_, _statePromise_) {
poolId = _poolId_;
statePromise = _statePromise_;
return service;
}
function allowed(/*item*/) {
return $q.all([
statePromise,
// This rule is made up and should therefore always pass. At some point there will
// likely be a valid rule similar to this that we will want to use.
policy.ifAllowed({ rules: [['neutron', 'pool_member_update']] })
]);
}
/**
* @ngdoc method
* @name open
*
* @description
* Open the modal.
*
* @param item The row item from the table action.
* @returns undefined
*/
function open(item) {
var spec = {
backdrop: 'static',
controller: 'EditWeightModalController as modal',
templateUrl: basePath + 'members/actions/edit-weight/modal.html',
resolve: {
poolId: function() {
return poolId;
},
member: function() {
return item;
}
}
};
$uibModal.open(spec).result.then(onModalClose);
}
function onModalClose() {
toastService.add('success', gettext('Pool member weight has been updated.'));
$route.reload();
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000176 00000000000 011221 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000002764 13245511613 034007 0 ustar zuul zuul 0000000 0000000
The weight of a member determines the portion of requests or connections it services compared to the other members of the pool.
././@LongLink 0000000 0000000 0000000 00000000207 00000000000 011214 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.controller.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000004217 13245511613 034002 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2.members')
.controller('EditWeightModalController', EditWeightModalController);
EditWeightModalController.$inject = [
'$uibModalInstance',
'horizon.app.core.openstack-service-api.lbaasv2',
'horizon.framework.util.i18n.gettext',
// Dependencies injected with resolve by $uibModal.open
'poolId',
'member'
];
/**
* @ngdoc controller
* @name EditWeightModalController
* @description
* Controller used by the modal service for editing the weight of a pool member.
*
* @param $uibModalInstance The angular bootstrap $uibModalInstance service.
* @param api The LBaaS v2 API service.
* @param gettext The horizon gettext function for translation.
* @param poolId The pool ID.
* @param member The pool member to update.
*
* @returns The Edit Weight modal controller.
*/
function EditWeightModalController($uibModalInstance, api, gettext, poolId, member) {
var ctrl = this;
ctrl.weight = member.weight;
ctrl.cancel = cancel;
ctrl.save = save;
ctrl.saving = false;
ctrl.weightError = gettext('The weight must be a number between 1 and 256.');
function save() {
ctrl.saving = true;
return api.editMember(poolId, member.id, { weight: ctrl.weight })
.then(onSuccess, onFailure);
}
function cancel() {
$uibModalInstance.dismiss('cancel');
}
function onSuccess() {
$uibModalInstance.close();
}
function onFailure() {
ctrl.saving = false;
}
}
})();
././@LongLink 0000000 0000000 0000000 00000000211 00000000000 011207 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.service.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000006751 13245511613 034007 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
describe('LBaaS v2 Member Edit Weight Service', function() {
var service, policy, $scope, $route, $uibModal, toast;
var member = { id: 'member1' };
var fakePromise = function(response) {
return {
then: function(func) {
return func(response);
}
};
};
function allowed(item) {
spyOn(policy, 'ifAllowed').and.returnValue(true);
var promise = service.allowed(item);
var allowed;
promise.then(function() {
allowed = true;
}, function() {
allowed = false;
});
$scope.$apply();
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'pool_member_update']]});
return allowed;
}
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.widgets'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
$provide.value('$uibModal', {
open: function() {
return {
result: fakePromise()
};
}
});
}));
beforeEach(inject(function ($injector) {
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
toast = $injector.get('horizon.framework.widgets.toast.service');
$scope = $injector.get('$rootScope').$new();
$route = $injector.get('$route');
$uibModal = $injector.get('$uibModal');
service = $injector.get(
'horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service');
service.init('pool1', fakePromise());
}));
it('should have the "allowed" and "perform" functions', function() {
expect(service.allowed).toBeDefined();
expect(service.perform).toBeDefined();
});
it('should check policy to allow the action', function() {
expect(allowed(member)).toBe(true);
});
it('should open the modal', function() {
spyOn($uibModal, 'open').and.callThrough();
service.perform(member);
$scope.$apply();
expect($uibModal.open.calls.count()).toBe(1);
});
it('should resolve data for passing into the modal', function() {
spyOn($uibModal, 'open').and.callThrough();
service.perform(member);
$scope.$apply();
var resolve = $uibModal.open.calls.argsFor(0)[0].resolve;
expect(resolve).toBeDefined();
expect(resolve.poolId()).toBe('pool1');
expect(resolve.member()).toBe(member);
});
it('should show message and reload page upon closing modal', function() {
spyOn(toast, 'add');
spyOn($route, 'reload');
service.perform(member);
$scope.$apply();
expect(toast.add).toHaveBeenCalledWith('success', 'Pool member weight has been updated.');
expect($route.reload).toHaveBeenCalled();
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000214 00000000000 011212 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actions/edit-weight/modal.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/actio0000666 0001751 0001751 00000005750 13245511613 034005 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function () {
'use strict';
describe('LBaaS v2 Member Edit Weight Controller', function() {
var ctrl, api, $controller, $uibModalInstance, $scope, $q;
var fail = false;
function makePromise(reject) {
var def = $q.defer();
def[reject ? 'reject' : 'resolve']();
return def.promise;
}
beforeEach(module('horizon.framework.util.i18n'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
$provide.value('$uibModalInstance', {
close: angular.noop,
dismiss: angular.noop
});
$provide.value('poolId', 'pool1');
$provide.value('member', {
id: 'member1',
weight: 1
});
$provide.value('horizon.app.core.openstack-service-api.lbaasv2', {
editMember: function() {
return makePromise(fail);
}
});
}));
beforeEach(inject(function ($injector) {
api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
$controller = $injector.get('$controller');
$uibModalInstance = $injector.get('$uibModalInstance');
$scope = $injector.get('$rootScope').$new();
$q = $injector.get('$q');
ctrl = $controller('EditWeightModalController');
}));
it('should define controller properties', function() {
expect(ctrl.cancel).toBeDefined();
expect(ctrl.save).toBeDefined();
expect(ctrl.saving).toBe(false);
expect(ctrl.weight).toBe(1);
expect(ctrl.weightError).toBe('The weight must be a number between 1 and 256.');
});
it('should edit member weight', function() {
spyOn(api, 'editMember').and.callThrough();
spyOn($uibModalInstance, 'close');
ctrl.save();
$scope.$apply();
expect(ctrl.saving).toBe(true);
expect(api.editMember).toHaveBeenCalledWith('pool1', 'member1', { weight: 1 });
expect($uibModalInstance.close).toHaveBeenCalled();
});
it('should dismiss modal if cancel clicked', function() {
spyOn($uibModalInstance, 'dismiss');
ctrl.cancel();
expect($uibModalInstance.dismiss).toHaveBeenCalledWith('cancel');
});
it('should not dismiss modal if save fails', function() {
fail = true;
spyOn($uibModalInstance, 'dismiss');
ctrl.save();
$scope.$apply();
expect($uibModalInstance.dismiss).not.toHaveBeenCalled();
expect(ctrl.saving).toBe(false);
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000170 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table0000666 0001751 0001751 00000006566 13245511613 034003 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
* Copyright 2017 Walmart.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 Members Table Controller', function() {
var controller, lbaasv2API, membersService, scope;
var items = [{ foo: 'bar' }];
var apiFail = false;
function fakeAPI() {
return {
then: function(success, fail) {
if (apiFail && fail) {
fail();
} else {
success({ data: { items: items } });
}
}
};
}
///////////////////////
beforeEach(module('horizon.framework.widgets.toast'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
$provide.value('$uibModal', {});
}));
beforeEach(inject(function($injector) {
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
membersService = $injector.get('horizon.dashboard.project.lbaasv2.members.service');
controller = $injector.get('$controller');
spyOn(lbaasv2API, 'getMembers').and.callFake(fakeAPI);
spyOn(membersService, 'associateMemberStatuses');
}));
function createController() {
return controller('MembersTableController', {
$scope: scope,
$routeParams: {
loadbalancerId: 'loadbaancerId',
listenerId: 'listenerId',
poolId: 'poolId'
}});
}
it('should initialize the controller properties correctly', function() {
var ctrl = createController();
expect(ctrl.items).toEqual([]);
expect(ctrl.src).toEqual(items);
expect(ctrl.loading).toBe(false);
expect(ctrl.error).toBe(false);
expect(ctrl.checked).toEqual({});
expect(ctrl.loadbalancerId).toBeDefined();
expect(ctrl.listenerId).toBeDefined();
expect(ctrl.poolId).toBeDefined();
expect(ctrl.rowActions).toBeDefined();
expect(ctrl.batchActions).toBeDefined();
expect(ctrl.operatingStatus).toBeDefined();
expect(ctrl.provisioningStatus).toBeDefined();
});
it('should invoke lbaasv2 apis', function() {
var ctrl = createController();
expect(lbaasv2API.getMembers).toHaveBeenCalled();
expect(ctrl.src.length).toBe(1);
});
it('should invoke the "associateMemberStatuses" method', function() {
var ctrl = createController();
expect(membersService.associateMemberStatuses).toHaveBeenCalledWith(
ctrl.loadbalancerId, ctrl.listenerId, ctrl.poolId, ctrl.src);
});
it('should show error if loading fails', function() {
apiFail = true;
var ctrl = createController();
expect(ctrl.src.length).toBe(0);
expect(ctrl.error).toBe(true);
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000171 00000000000 011214 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detail.controller.spec.js neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/detai0000666 0001751 0001751 00000010505 13245511613 033766 0 ustar zuul zuul 0000000 0000000 /*
* Copyright 2016 IBM Corp.
*
* 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.
*/
(function() {
'use strict';
describe('LBaaS v2 Member Detail Controller', function() {
var $controller, lbaasv2API, membersService, apiFail, qAllFail, actions;
function fakePromise(data, reject) {
return {
then: function(success, fail) {
if (reject) {
fail();
} else {
success({ data: data });
}
return fakePromise();
}
};
}
function fakeAPI() {
return fakePromise('foo', apiFail);
}
function loadbalancerAPI() {
return fakePromise({ provisioning_status: 'ACTIVE' });
}
function qAll() {
return fakePromise(null, qAllFail);
}
function createController() {
return $controller('MemberDetailController', {
$routeParams: {
loadbalancerId: 'loadbalancerId',
listenerId: 'listenerId',
poolId: 'poolId',
memberId: 'memberId'
}
});
}
///////////////////////
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.widgets.toast'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
apiFail = false;
qAllFail = false;
$provide.value('$q', { all: qAll });
$provide.value('$uibModal', {});
$provide.value('horizon.dashboard.project.lbaasv2.members.actions.rowActions', {
init: function() {
return {
actions: 'member-actions'
};
}
});
}));
beforeEach(inject(function($injector) {
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
actions = $injector.get('horizon.dashboard.project.lbaasv2.members.actions.rowActions');
membersService = $injector.get('horizon.dashboard.project.lbaasv2.members.service');
spyOn(lbaasv2API, 'getMember').and.callFake(fakeAPI);
spyOn(lbaasv2API, 'getPool').and.callFake(fakeAPI);
spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI);
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
spyOn(actions, 'init').and.callThrough();
spyOn(membersService, 'associateMemberStatuses');
$controller = $injector.get('$controller');
}));
it('should invoke lbaasv2 apis', function() {
var ctrl = createController();
expect(lbaasv2API.getMember).toHaveBeenCalledWith('poolId','memberId');
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId');
expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId');
expect(ctrl.loadbalancerId).toBeDefined();
expect(ctrl.listenerId).toBeDefined();
expect(ctrl.poolId).toBeDefined();
expect(ctrl.operatingStatus).toBeDefined();
expect(ctrl.provisioningStatus).toBeDefined();
expect(ctrl.actions).toBe('member-actions');
expect(actions.init).toHaveBeenCalledWith('loadbalancerId', 'poolId');
});
it('should invoke the "associateMemberStatuses" method', function() {
var ctrl = createController();
expect(membersService.associateMemberStatuses).toHaveBeenCalledWith(
ctrl.loadbalancerId, ctrl.listenerId, ctrl.poolId, [ctrl.member]);
});
it('should throw error on API fail', function() {
apiFail = true;
var init = function() {
createController();
};
expect(init).toThrow();
});
it('should set error state if any APIs fail', function() {
qAllFail = true;
var ctrl = createController();
expect(ctrl.loading).toBe(false);
expect(ctrl.error).toBe(true);
});
});
})();
././@LongLink 0000000 0000000 0000000 00000000152 00000000000 011213 L ustar 0000000 0000000 neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table.html neutron-lbaas-dashboard-4.0.0/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/members/table0000666 0001751 0001751 00000006474 13245511613 034001 0 ustar zuul zuul 0000000 0000000