summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lyle <david.lyle@intel.com>2015-05-29 11:10:12 -0600
committerDan Nguyen <dan.nguyens.mail@gmail.com>2015-11-24 23:56:10 +0000
commit46a739531f9c2eb55c65000eca6b5737b16145ab (patch)
tree98ae80edd8f9fbe35dd86322848a8c82987db3ae
parentab7d5c3ec5317dea2495b958c9f82b2716ba4b5a (diff)
downloadhorizon-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
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/api_access/tables.py20
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/api_access/tests.py24
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/api_access/urls.py1
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/api_access/views.py20
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/_credentials.html6
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc.sh.template17
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/api_access/openrc_v2.sh.template39
-rw-r--r--openstack_dashboard/test/helpers.py5
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,