Downloadable Kubernetes configuration file
Kubernetes can use OpenStack application credentials for authentication. Generate a kubeconfig file and make it available to download along with the openrc and clouds.yaml files. blueprint kubernetes-config-gen Change-Id: I298370e7abf4f0d480bd5199060f24bab6d6daaa
This commit is contained in:
parent
a7a04da657
commit
f381f4dd3c
@ -7,7 +7,7 @@ Settings Reference
|
|||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
Horizon's settings broadly fall into three categories:
|
Horizon's settings broadly fall into four categories:
|
||||||
|
|
||||||
* `General Settings`_: this includes visual settings like the modal backdrop
|
* `General Settings`_: this includes visual settings like the modal backdrop
|
||||||
style, bug url and theme configuration, as well as settings that affect every
|
style, bug url and theme configuration, as well as settings that affect every
|
||||||
@ -21,6 +21,8 @@ Horizon's settings broadly fall into three categories:
|
|||||||
should read the `Django settings documentation
|
should read the `Django settings documentation
|
||||||
<https://docs.djangoproject.com/en/dev/topics/settings/>`_ to see the other
|
<https://docs.djangoproject.com/en/dev/topics/settings/>`_ to see the other
|
||||||
options available to you.
|
options available to you.
|
||||||
|
* `Other Settings`_: settings which do not fall into any of the above
|
||||||
|
categories.
|
||||||
|
|
||||||
To modify your settings, you have two options:
|
To modify your settings, you have two options:
|
||||||
|
|
||||||
@ -2521,3 +2523,51 @@ Default: Absolute paths for `horizon/locale`, `openstack_auth/locale` and
|
|||||||
Django uses relative paths by default so it causes localization issues
|
Django uses relative paths by default so it causes localization issues
|
||||||
depending on your runtime settings. To avoid this we recommend to use absolute
|
depending on your runtime settings. To avoid this we recommend to use absolute
|
||||||
paths for directories with locales.
|
paths for directories with locales.
|
||||||
|
|
||||||
|
Other Settings
|
||||||
|
==============
|
||||||
|
|
||||||
|
KUBECONFIG_ENABLED
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. versionadded:: TBD
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Kubernetes clusters can use Keystone as an external identity provider.
|
||||||
|
Horizon can generate a ``kubeconfig`` file from the application credentials
|
||||||
|
control panel which can be used for authenticating with a Kubernetes cluster.
|
||||||
|
This setting enables this behavior.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
`KUBECONFIG_KUBERNETES_URL`_ and `KUBECONFIG_CERTIFICATE_AUTHORITY_DATA`_
|
||||||
|
to provide parameters for the ``kubeconfig`` file.
|
||||||
|
|
||||||
|
KUBECONFIG_KUBERNETES_URL
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. versionadded:: TBD
|
||||||
|
|
||||||
|
Default: ``""``
|
||||||
|
|
||||||
|
A Kubernetes API endpoint URL to be included in the generated ``kubeconfig``
|
||||||
|
file.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
`KUBECONFIG_ENABLED`_ to enable the ``kubeconfig`` file generation.
|
||||||
|
|
||||||
|
KUBECONFIG_CERTIFICATE_AUTHORITY_DATA
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: TBD
|
||||||
|
|
||||||
|
Default: ``""``
|
||||||
|
|
||||||
|
Kubernetes API endpoint certificate authority data to be included in the
|
||||||
|
generated ``kubeconfig`` file.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
`KUBECONFIG_ENABLED`_ to enable the ``kubeconfig`` file generation.
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.forms import widgets
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.decorators.debug import sensitive_variables
|
from django.views.decorators.debug import sensitive_variables
|
||||||
|
|
||||||
@ -49,6 +51,10 @@ class CreateApplicationCredentialForm(forms.SelfHandlingForm):
|
|||||||
required=False)
|
required=False)
|
||||||
unrestricted = forms.BooleanField(label=_("Unrestricted (dangerous)"),
|
unrestricted = forms.BooleanField(label=_("Unrestricted (dangerous)"),
|
||||||
required=False)
|
required=False)
|
||||||
|
kubernetes_namespace = forms.CharField(max_length=255,
|
||||||
|
label=_("Kubernetes Namespace"),
|
||||||
|
initial="default",
|
||||||
|
required=False)
|
||||||
|
|
||||||
def __init__(self, request, *args, **kwargs):
|
def __init__(self, request, *args, **kwargs):
|
||||||
self.next_view = kwargs.pop('next_view', None)
|
self.next_view = kwargs.pop('next_view', None)
|
||||||
@ -58,6 +64,8 @@ class CreateApplicationCredentialForm(forms.SelfHandlingForm):
|
|||||||
role_names = [role['name'] for role in role_list]
|
role_names = [role['name'] for role in role_list]
|
||||||
role_choices = ((name, name) for name in role_names)
|
role_choices = ((name, name) for name in role_names)
|
||||||
self.fields['roles'].choices = role_choices
|
self.fields['roles'].choices = role_choices
|
||||||
|
if not settings.KUBECONFIG_ENABLED:
|
||||||
|
self.fields['kubernetes_namespace'].widget = widgets.HiddenInput()
|
||||||
|
|
||||||
# We have to protect the entire "data" dict because it contains the
|
# We have to protect the entire "data" dict because it contains the
|
||||||
# secret string.
|
# secret string.
|
||||||
@ -98,6 +106,8 @@ class CreateApplicationCredentialForm(forms.SelfHandlingForm):
|
|||||||
)
|
)
|
||||||
self.request.session['application_credential'] = \
|
self.request.session['application_credential'] = \
|
||||||
new_app_cred.to_dict()
|
new_app_cred.to_dict()
|
||||||
|
(self.request.session['application_credential']
|
||||||
|
['kubernetes_namespace']) = data['kubernetes_namespace']
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
return self.next_view.as_view()(request)
|
return self.next_view.as_view()(request)
|
||||||
except exceptions.Conflict:
|
except exceptions.Conflict:
|
||||||
|
@ -40,4 +40,12 @@
|
|||||||
actions, check "unrestricted".
|
actions, check "unrestricted".
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
{% if kubeconfig_enabled %}
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
You can optionally provide a Kubernetes Namespace. It will be included in the
|
||||||
|
kubeconfig file which can be downloaded from the next screen.
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -31,5 +31,11 @@
|
|||||||
<span class="fa fa-download"></span>
|
<span class="fa fa-download"></span>
|
||||||
{{ download_clouds_yaml_label }}
|
{{ download_clouds_yaml_label }}
|
||||||
</a>
|
</a>
|
||||||
|
{% if download_kubeconfig_url %}
|
||||||
|
<a href="{{ download_kubeconfig_url }}" class="btn btn-default">
|
||||||
|
<span class="fa fa-download"></span>
|
||||||
|
{{ download_kubeconfig_label }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
<a onClick="location.href='{{cancel_url}}'" href="{{ cancel_url }}" class="btn btn-default">{{ cancel_label }}</a>
|
<a onClick="location.href='{{cancel_url}}'" href="{{ cancel_url }}" class="btn btn-default">{{ cancel_label }}</a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Config
|
||||||
|
clusters:
|
||||||
|
- name: kubernetes
|
||||||
|
cluster:
|
||||||
|
server: {{ kubernetes_url }}
|
||||||
|
certificate-authority-data: {{ kubernetes_certificate_authority_data }}
|
||||||
|
contexts:
|
||||||
|
- name: kubernetes
|
||||||
|
context:
|
||||||
|
cluster: kubernetes
|
||||||
|
user: {{ user }}
|
||||||
|
namespace: {{ kubernetes_namespace }}
|
||||||
|
current-context: kubernetes
|
||||||
|
users:
|
||||||
|
- name: {{ user }}
|
||||||
|
user:
|
||||||
|
exec:
|
||||||
|
apiVersion: client.authentication.k8s.io/v1beta1
|
||||||
|
command: bin/kubectl-keystone-auth
|
||||||
|
args:
|
||||||
|
- "--keystone-url={{ auth_url }}
|
||||||
|
- "--domain-name=none"
|
||||||
|
- "--user-name={{ user }}"
|
||||||
|
- "--application-credential-id={{ application_credential_id }}"
|
||||||
|
- "--application-credential-secret={{ application_credential_secret }}"
|
@ -28,6 +28,8 @@ urlpatterns = [
|
|||||||
views.CreateSuccessfulView.as_view(), name='success'),
|
views.CreateSuccessfulView.as_view(), name='success'),
|
||||||
url(r'^download_openrc/$',
|
url(r'^download_openrc/$',
|
||||||
views.download_rc_file, name='download_openrc'),
|
views.download_rc_file, name='download_openrc'),
|
||||||
|
url(r'^download_kubeconfig/$',
|
||||||
|
views.download_kubeconfig_file, name='download_kubeconfig'),
|
||||||
url(r'^download_clouds_yaml/$',
|
url(r'^download_clouds_yaml/$',
|
||||||
views.download_clouds_yaml_file, name='download_clouds_yaml'),
|
views.download_clouds_yaml_file, name='download_clouds_yaml'),
|
||||||
]
|
]
|
||||||
|
@ -86,6 +86,11 @@ class CreateView(forms.ModalFormView):
|
|||||||
kwargs['next_view'] = CreateSuccessfulView
|
kwargs['next_view'] = CreateSuccessfulView
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(CreateView, self).get_context_data(**kwargs)
|
||||||
|
context['kubeconfig_enabled'] = settings.KUBECONFIG_ENABLED
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class CreateSuccessfulView(forms.ModalFormView):
|
class CreateSuccessfulView(forms.ModalFormView):
|
||||||
template_name = 'identity/application_credentials/success.html'
|
template_name = 'identity/application_credentials/success.html'
|
||||||
@ -97,15 +102,20 @@ class CreateSuccessfulView(forms.ModalFormView):
|
|||||||
cancel_label = _("Close")
|
cancel_label = _("Close")
|
||||||
download_openrc_label = _("Download openrc file")
|
download_openrc_label = _("Download openrc file")
|
||||||
download_clouds_yaml_label = _("Download clouds.yaml")
|
download_clouds_yaml_label = _("Download clouds.yaml")
|
||||||
|
download_kubeconfig_label = _("Download kubeconfig file")
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(CreateSuccessfulView, self).get_context_data(**kwargs)
|
context = super(CreateSuccessfulView, self).get_context_data(**kwargs)
|
||||||
context['download_openrc_label'] = self.download_openrc_label
|
context['download_openrc_label'] = self.download_openrc_label
|
||||||
context['download_clouds_yaml_label'] = self.download_clouds_yaml_label
|
context['download_clouds_yaml_label'] = self.download_clouds_yaml_label
|
||||||
|
context['download_kubeconfig_label'] = self.download_kubeconfig_label
|
||||||
context['download_openrc_url'] = reverse(
|
context['download_openrc_url'] = reverse(
|
||||||
'horizon:identity:application_credentials:download_openrc')
|
'horizon:identity:application_credentials:download_openrc')
|
||||||
context['download_clouds_yaml_url'] = reverse(
|
context['download_clouds_yaml_url'] = reverse(
|
||||||
'horizon:identity:application_credentials:download_clouds_yaml')
|
'horizon:identity:application_credentials:download_clouds_yaml')
|
||||||
|
if settings.KUBECONFIG_ENABLED:
|
||||||
|
context['download_kubeconfig_url'] = reverse(
|
||||||
|
'horizon:identity:application_credentials:download_kubeconfig')
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
@ -125,12 +135,18 @@ def _get_context(request):
|
|||||||
interface = 'public'
|
interface = 'public'
|
||||||
region = getattr(request.user, 'services_region', '')
|
region = getattr(request.user, 'services_region', '')
|
||||||
app_cred = request.session['application_credential']
|
app_cred = request.session['application_credential']
|
||||||
context = dict(auth_url=auth_url,
|
context = {
|
||||||
interface=interface,
|
'auth_url': auth_url,
|
||||||
region=region,
|
'interface': interface,
|
||||||
application_credential_id=app_cred['id'],
|
'region': region,
|
||||||
application_credential_name=app_cred['name'],
|
'user': request.user,
|
||||||
application_credential_secret=app_cred['secret'])
|
'application_credential_id': app_cred['id'],
|
||||||
|
'application_credential_name': app_cred['name'],
|
||||||
|
'application_credential_secret': app_cred['secret'],
|
||||||
|
'kubernetes_namespace': app_cred['kubernetes_namespace'],
|
||||||
|
'kubernetes_url': settings.KUBECONFIG_KUBERNETES_URL,
|
||||||
|
'kubernetes_certificate_authority_data':
|
||||||
|
settings.KUBECONFIG_CERTIFICATE_AUTHORITY_DATA}
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@ -166,6 +182,14 @@ def download_clouds_yaml_file(request):
|
|||||||
return _render_attachment(filename, template, context, request)
|
return _render_attachment(filename, template, context, request)
|
||||||
|
|
||||||
|
|
||||||
|
def download_kubeconfig_file(request):
|
||||||
|
context = _get_context(request)
|
||||||
|
template = 'identity/application_credentials/kubeconfig.template'
|
||||||
|
filename = 'app-cred-%s-kubeconfig' % context['application_credential_name']
|
||||||
|
response = _render_attachment(filename, template, context, request)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
class DetailView(views.HorizonTemplateView):
|
class DetailView(views.HorizonTemplateView):
|
||||||
template_name = 'identity/application_credentials/detail.html'
|
template_name = 'identity/application_credentials/detail.html'
|
||||||
page_title = "{{ application_credential.name }}"
|
page_title = "{{ application_credential.name }}"
|
||||||
|
@ -374,3 +374,11 @@ REST_API_REQUIRED_SETTINGS = [
|
|||||||
# and are not encrypted on the browser. This is an experimental API and
|
# and are not encrypted on the browser. This is an experimental API and
|
||||||
# may be deprecated in the future without notice.
|
# may be deprecated in the future without notice.
|
||||||
REST_API_ADDITIONAL_SETTINGS = []
|
REST_API_ADDITIONAL_SETTINGS = []
|
||||||
|
|
||||||
|
# Kubernetes clusters can use Keystone as an external identity provider.
|
||||||
|
# Horizon can generate a 'kubeconfig' file from the application credentials
|
||||||
|
# control panel which can be used for authenticating with a Kubernetes cluster.
|
||||||
|
# These settings control the kubeconfig parameters.
|
||||||
|
KUBECONFIG_ENABLED = False
|
||||||
|
KUBECONFIG_KUBERNETES_URL = ""
|
||||||
|
KUBECONFIG_CERTIFICATE_AUTHORITY_DATA = ""
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
[`blueprint kubernetes-config-gen <https://blueprints.launchpad.net/horizon/+spec/kubernetes-config-gen>`_]
|
||||||
|
Horizon now supports the optional automatic generation of a Kubernetes
|
||||||
|
configuration file (kubeconfig) based on application credentials. Adds
|
||||||
|
a new download button for this purpose in the application credentials
|
||||||
|
creation dialog.
|
Loading…
x
Reference in New Issue
Block a user