diff options
author | David Lyle <david.lyle@intel.com> | 2015-05-29 11:10:12 -0600 |
---|---|---|
committer | Dan Nguyen <dan.nguyens.mail@gmail.com> | 2015-11-24 23:56:10 +0000 |
commit | 46a739531f9c2eb55c65000eca6b5737b16145ab (patch) | |
tree | 98ae80edd8f9fbe35dd86322848a8c82987db3ae | |
parent | ab7d5c3ec5317dea2495b958c9f82b2716ba4b5a (diff) | |
download | horizon-46a739531f9c2eb55c65000eca6b5737b16145ab.tar.gz |
Adding download for openrc file for keystone v3
The existing openrc file download only works for keystone v2. Regardless
of whether v3 is enabled in Horizon.
This adds support for both. A v2.0 and a v3 compatible openrc file
download. A couple of different situations are covered.
1) support for keystone v2 only: OPENSTACK_API_VERSION={'identity': 2.0}
In this case only the v2 option is shown.
2) Use of keystone v3 in a potentially mixed environment. Since it is
possible to use keystone v2 and v3 in the same enviroment, having
OPENSTACK_API_VERSION={'identity': 3} displays options for downloading
v2 or v3 compatible openrc files.
Rationale for making the existing methods and urls support v3+. By
moving the v2.0 functionality to new version specific methods, they can
be more easily excised when v2 is obsolete and we're left with the newer
version support.
Change-Id: I29c62dc7436cc39adc1a4af9d90ceb6767e7a177
Closes-Bug: #1460150
8 files changed, 118 insertions, 14 deletions
diff --git a/openstack_dashboard/dashboards/project/access_and_security/api_access/tables.py b/openstack_dashboard/dashboards/project/access_and_security/api_access/tables.py index 1eaa1b0b3..1f547a3bd 100644 --- a/openstack_dashboard/dashboards/project/access_and_security/api_access/tables.py +++ b/openstack_dashboard/dashboards/project/access_and_security/api_access/tables.py @@ -15,6 +15,8 @@ from django.template.defaultfilters import title # noqa from django.utils.translation import ugettext_lazy as _ +from openstack_auth import utils + from horizon import tables from openstack_dashboard import api @@ -42,11 +44,22 @@ class DownloadEC2(tables.LinkAction): class DownloadOpenRC(tables.LinkAction): name = "download_openrc" - verbose_name = _("Download OpenStack RC File") - verbose_name_plural = _("Download OpenStack RC File") + verbose_name = _("Download OpenStack RC File v3") + verbose_name_plural = _("Download OpenStack RC File v3") icon = "download" url = "horizon:project:access_and_security:api_access:openrc" + def allowed(self, request, datum=None): + return utils.get_keystone_version() >= 3 + + +class DownloadOpenRCv2(tables.LinkAction): + name = "download_openrc_v2" + verbose_name = _("Download OpenStack RC File v2.0") + verbose_name_plural = _("Download OpenStack RC File v2.0") + icon = "download" + url = "horizon:project:access_and_security:api_access:openrcv2" + class ViewCredentials(tables.LinkAction): name = "view_credentials" @@ -67,4 +80,5 @@ class EndpointsTable(tables.DataTable): name = "endpoints" verbose_name = _("API Endpoints") multi_select = False - table_actions = (DownloadOpenRC, DownloadEC2, ViewCredentials) + table_actions = (DownloadOpenRCv2, DownloadOpenRC, DownloadEC2, + ViewCredentials) diff --git a/openstack_dashboard/dashboards/project/access_and_security/api_access/tests.py b/openstack_dashboard/dashboards/project/access_and_security/api_access/tests.py index ad0e5a80f..0c1d18c4a 100644 --- a/openstack_dashboard/dashboards/project/access_and_security/api_access/tests.py +++ b/openstack_dashboard/dashboards/project/access_and_security/api_access/tests.py @@ -14,6 +14,7 @@ from django.core.urlresolvers import reverse from django.http import HttpRequest # noqa +from django.test.utils import override_settings # noqa from mox3.mox import IsA # noqa @@ -24,6 +25,7 @@ from openstack_dashboard.test import helpers as test API_URL = "horizon:project:access_and_security:api_access" EC2_URL = reverse(API_URL + ":ec2") OPENRC_URL = reverse(API_URL + ":openrc") +OPENRCV2_URL = reverse(API_URL + ":openrcv2") CREDS_URL = reverse(API_URL + ":view_credentials") @@ -51,15 +53,33 @@ class APIAccessTests(test.TestCase): self.assertEqual(res.status_code, 200) self.assertEqual(res['content-type'], 'application/zip') + def test_openrcv2_credentials(self): + res = self.client.get(OPENRCV2_URL) + self.assertEqual(res.status_code, 200) + openrc = 'project/access_and_security/api_access/openrc_v2.sh.template' + self.assertTemplateUsed(res, openrc) + name = 'export OS_USERNAME="{}"'.format(self.request.user.username) + t_id = 'export OS_TENANT_ID={}'.format(self.request.user.tenant_id) + domain = 'export OS_USER_DOMAIN_NAME="{}"'.format( + self.request.user.user_domain_name) + self.assertIn(name.encode('utf-8'), res.content) + self.assertIn(t_id.encode('utf-8'), res.content) + # domain content should not be present for v2 + self.assertNotIn(domain.encode('utf-8'), res.content) + + @override_settings(OPENSTACK_API_VERSIONS={"identity": 3}) def test_openrc_credentials(self): res = self.client.get(OPENRC_URL) self.assertEqual(res.status_code, 200) openrc = 'project/access_and_security/api_access/openrc.sh.template' self.assertTemplateUsed(res, openrc) name = 'export OS_USERNAME="{}"'.format(self.request.user.username) - id = 'export OS_TENANT_ID={}'.format(self.request.user.tenant_id) + p_id = 'export OS_PROJECT_ID={}'.format(self.request.user.tenant_id) + domain = 'export OS_USER_DOMAIN_NAME="{}"'.format( + self.request.user.user_domain_name) self.assertIn(name.encode('utf-8'), res.content) - self.assertIn(id.encode('utf-8'), res.content) + self.assertIn(p_id.encode('utf-8'), res.content) + self.assertIn(domain.encode('utf-8'), res.content) @test.create_stubs({api.keystone: ("list_ec2_credentials",)}) def test_credential_api(self): diff --git a/openstack_dashboard/dashboards/project/access_and_security/api_access/urls.py b/openstack_dashboard/dashboards/project/access_and_security/api_access/urls.py index 8c86ae775..51b090f22 100644 --- a/openstack_dashboard/dashboards/project/access_and_security/api_access/urls.py +++ b/openstack_dashboard/dashboards/project/access_and_security/api_access/urls.py @@ -27,6 +27,7 @@ urlpatterns = patterns( '', url(r'^ec2/$', views.download_ec2_bundle, name='ec2'), url(r'^openrc/$', views.download_rc_file, name='openrc'), + url(r'^openrcv2/$', views.download_rc_file_v2, name='openrcv2'), url(r'^view_credentials/$', views.CredentialsView.as_view(), name='view_credentials') ) diff --git a/openstack_dashboard/dashboards/project/access_and_security/api_access/views.py b/openstack_dashboard/dashboards/project/access_and_security/api_access/views.py index d71bb1a84..b5bea20a9 100644 --- a/openstack_dashboard/dashboards/project/access_and_security/api_access/views.py +++ b/openstack_dashboard/dashboards/project/access_and_security/api_access/views.py @@ -22,6 +22,8 @@ from django import shortcuts from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ +from openstack_auth import utils + from horizon import exceptions from horizon import forms from horizon import messages @@ -112,11 +114,25 @@ def download_ec2_bundle(request): return response +def download_rc_file_v2(request): + template = 'project/access_and_security/api_access/openrc_v2.sh.template' + context = _get_openrc_credentials(request) + return _download_rc_file_for_template(request, context, template) + + def download_rc_file(request): template = 'project/access_and_security/api_access/openrc.sh.template' - try: - context = _get_openrc_credentials(request) + context = _get_openrc_credentials(request) + # make v3 specific changes + context['user_domain_name'] = request.user.user_domain_name + # sanity fix for removing v2.0 from the url if present + context['auth_url'] = utils.fix_auth_url_version(context['auth_url']) + return _download_rc_file_for_template(request, context, template) + + +def _download_rc_file_for_template(request, context, template): + try: response = shortcuts.render(request, template, context, diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/_credentials.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/_credentials.html index 85cec091a..25cdd7b4d 100644 --- a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/_credentials.html +++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/_credentials.html @@ -13,6 +13,12 @@ <label class="control-label">{% trans "User Name" %}</label> <input type="text" class="form-control" readonly value="{{ openrc_creds.user }}"> </div> + {% if "user_domain_name" in openrc_creds %} + <div class="form-group"> + <label class="control-label">{% trans "Domain Name" %}</label> + <input type="text" class="form-control" readonly value="{{ openrc_creds.user_domain_name }}"> + </div> + {% endif %} <div class="form-group"> <label class="control-label">{% trans "Project Name" %}</label> <input type="text" class="form-control" readonly value="{{ openrc_creds.tenant_name }}"> diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc.sh.template b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc.sh.template index 2b6a7098f..4818d5173 100644 --- a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc.sh.template +++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc.sh.template @@ -1,4 +1,4 @@ -{% load shellfilter %}#!/bin/bash +{% load shellfilter %}#!/usr/bin/env bash # To use an OpenStack cloud you need to authenticate against the Identity # service named keystone, which returns a **Token** and **Service Catalog**. @@ -7,17 +7,22 @@ # Storage, and Networking (code-named nova, glance, keystone, swift, # cinder, and neutron). # -# *NOTE*: Using the 2.0 *Identity API* does not necessarily mean any other -# OpenStack API is version 2.0. For example, your cloud provider may implement +# *NOTE*: Using the 3 *Identity API* does not necessarily mean any other +# OpenStack API is version 3. For example, your cloud provider may implement # Image API v1.1, Block Storage API v2, and Compute API v2.0. OS_AUTH_URL is # only for the Identity API served through keystone. export OS_AUTH_URL={{ auth_url }} -# With the addition of Keystone we have standardized on the term **tenant** +# With the addition of Keystone we have standardized on the term **project** # as the entity that owns the resources. -export OS_TENANT_ID={{ tenant_id }} -export OS_TENANT_NAME="{{ tenant_name|shellfilter }}" +export OS_PROJECT_ID={{ tenant_id }} export OS_PROJECT_NAME="{{ tenant_name|shellfilter }}" +export OS_USER_DOMAIN_NAME="{{ user_domain_name|shellfilter }}" +if [ -z "$OS_USER_DOMAIN_NAME" ]; then unset OS_USER_DOMAIN_NAME; fi + +# unset v2.0 items in case set +unset OS_TENANT_ID +unset OS_TENANT_NAME # In addition to the owning entity (tenant), OpenStack stores the entity # performing the action as the **user**. diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc_v2.sh.template b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc_v2.sh.template new file mode 100644 index 000000000..d9823a3bb --- /dev/null +++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc_v2.sh.template @@ -0,0 +1,39 @@ +{% load shellfilter %}#!/usr/bin/env bash + +# To use an OpenStack cloud you need to authenticate against the Identity +# service named keystone, which returns a **Token** and **Service Catalog**. +# The catalog contains the endpoints for all services the user/tenant has +# access to - such as Compute, Image Service, Identity, Object Storage, Block +# Storage, and Networking (code-named nova, glance, keystone, swift, +# cinder, and neutron). +# +# *NOTE*: Using the 2.0 *Identity API* does not necessarily mean any other +# OpenStack API is version 2.0. For example, your cloud provider may implement +# Image API v1.1, Block Storage API v2, and Compute API v2.0. OS_AUTH_URL is +# only for the Identity API served through keystone. +export OS_AUTH_URL={{ auth_url }} + +# With the addition of Keystone we have standardized on the term **tenant** +# as the entity that owns the resources. +export OS_TENANT_ID={{ tenant_id }} +export OS_TENANT_NAME="{{ tenant_name|shellfilter }}" + +# unsetting v3 items in case set +unset OS_PROJECT_ID +unset OS_PROJECT_NAME +unset OS_USER_DOMAIN_NAME + +# In addition to the owning entity (tenant), OpenStack stores the entity +# performing the action as the **user**. +export OS_USERNAME="{{ user.username|shellfilter }}" + +# With Keystone you pass the keystone password. +echo "Please enter your OpenStack Password: " +read -sr OS_PASSWORD_INPUT +export OS_PASSWORD=$OS_PASSWORD_INPUT + +# If your configuration has multiple regions, we set that information here. +# OS_REGION_NAME is optional and only valid in certain environments. +export OS_REGION_NAME="{{ region|shellfilter }}" +# Don't leave a blank variable, unset it if it was empty +if [ -z "$OS_REGION_NAME" ]; then unset OS_REGION_NAME; fi diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py index b108d6be0..e1a8c2a2f 100644 --- a/openstack_dashboard/test/helpers.py +++ b/openstack_dashboard/test/helpers.py @@ -181,6 +181,7 @@ class TestCase(horizon_helpers.TestCase): token=self.token, username=self.user.name, domain_id=self.domain.id, + user_domain_name=self.domain.name, tenant_id=self.tenant.id, service_catalog=self.service_catalog, authorized_tenants=tenants) @@ -206,12 +207,14 @@ class TestCase(horizon_helpers.TestCase): def setActiveUser(self, id=None, token=None, username=None, tenant_id=None, service_catalog=None, tenant_name=None, roles=None, - authorized_tenants=None, enabled=True, domain_id=None): + authorized_tenants=None, enabled=True, domain_id=None, + user_domain_name=None): def get_user(request): return user.User(id=id, token=token, user=username, domain_id=domain_id, + user_domain_name=user_domain_name, tenant_id=tenant_id, service_catalog=service_catalog, roles=roles, |