Add Horizon Dockerfile and operator
Change-Id: I9bab4c3a66a33a4a8289509eb8c93232d56dfe6a
This commit is contained in:
parent
9451d3aaee
commit
be4e5eee89
1
Makefile
1
Makefile
@ -1,4 +1,5 @@
|
||||
images:
|
||||
docker build images/horizon -t vexxhost/horizon:latest
|
||||
docker build images/ceilometer --target ceilometer-agent-notification -t vexxhost/ceilometer-agent-notification:latest
|
||||
docker build images/mcrouter -t vexxhost/mcrouter:latest
|
||||
docker build images/mcrouter-exporter -t vexxhost/mcrouter-exporter:latest
|
||||
|
19
chart/crds/dashboard.openstack.org_horizons.yaml
Normal file
19
chart/crds/dashboard.openstack.org_horizons.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: horizons.dashboard.openstack.org
|
||||
spec:
|
||||
group: dashboard.openstack.org
|
||||
names:
|
||||
kind: Horizon
|
||||
listKind: HorizonList
|
||||
plural: horizons
|
||||
singular: horizon
|
||||
scope: Namespaced
|
||||
version: v1alpha1
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
@ -129,6 +129,26 @@ rules:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- dashboard.openstack.org
|
||||
resources:
|
||||
- horizons
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- dashboard.openstack.org
|
||||
resources:
|
||||
- horizons/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- infrastructure.vexxhost.cloud
|
||||
resources:
|
||||
|
@ -29,6 +29,8 @@ spec:
|
||||
args:
|
||||
- run
|
||||
- -m
|
||||
- openstack_operator.horizon
|
||||
- -m
|
||||
- openstack_operator.mcrouter
|
||||
- -m
|
||||
- openstack_operator.memcached
|
||||
|
9
config/samples/dashboard_v1alpha1_horizon.yaml
Normal file
9
config/samples/dashboard_v1alpha1_horizon.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
apiVersion: dashboard.openstack.org/v1alpha1
|
||||
kind: Horizon
|
||||
metadata:
|
||||
name: sample
|
||||
labels:
|
||||
prometheus: helm
|
||||
spec:
|
||||
ingress:
|
||||
host: "horizon.vexxhost.com"
|
48
images/horizon/Dockerfile
Normal file
48
images/horizon/Dockerfile
Normal file
@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM docker.io/opendevorg/python-builder as builder
|
||||
COPY bindep.txt /tmp/src/bindep.txt
|
||||
RUN assemble horizon==18.3.1 \
|
||||
python-memcached \
|
||||
heat-dashboard==2.0.0 \
|
||||
designate-dashboard==9.0.0 \
|
||||
neutron-vpnaas-dashboard==1.6.0 \
|
||||
octavia-dashboard==4.0.0 \
|
||||
sahara-dashboard==11.0.0 \
|
||||
magnum-ui==6.0.0
|
||||
|
||||
FROM docker.io/opendevorg/uwsgi-base
|
||||
COPY --from=builder /output/ /output
|
||||
RUN /output/install-from-bindep
|
||||
WORKDIR /usr/local/lib/python3.7/site-packages/openstack_dashboard
|
||||
RUN ln -s /etc/horizon/local_settings.py local/local_settings.py && \
|
||||
cp ../designatedashboard/enabled/*.py enabled/ && \
|
||||
cp ../heat_dashboard/enabled/*.py enabled/ && \
|
||||
cp ../magnum_ui/enabled/*.py enabled/ && \
|
||||
cp ../neutron_vpnaas_dashboard/enabled/*.py enabled/ && \
|
||||
cp ../octavia_dashboard/enabled/*.py enabled/ && \
|
||||
cp ../sahara_dashboard/enabled/*.py enabled/
|
||||
COPY *.svg ../static/dashboard/img/
|
||||
COPY manage.py .
|
||||
RUN python manage.py collectstatic --no-input && \
|
||||
python manage.py compress --force && \
|
||||
chown 1001 -R local/ ../static
|
||||
EXPOSE 8000
|
||||
ENV UWSGI_HTTP_SOCKET=:8000 \
|
||||
UWSGI_WSGI_FILE=/usr/local/lib/python3.7/site-packages/openstack_dashboard/wsgi/django.wsgi \
|
||||
UWSGI_CHECK_STATIC=/usr/local/lib/python3.7/site-packages/static/ \
|
||||
UWSGI_STATIC_MAP="/static=/usr/local/lib/python3.7/site-packages/static/" \
|
||||
UWSGI_MIME_FILE="/etc/mime.types"
|
3
images/horizon/bindep.txt
Normal file
3
images/horizon/bindep.txt
Normal file
@ -0,0 +1,3 @@
|
||||
gcc [compile]
|
||||
libc-dev [compile]
|
||||
mime-support
|
31
images/horizon/logo-splash.svg
Normal file
31
images/horizon/logo-splash.svg
Normal file
@ -0,0 +1,31 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98.43 118.4">
|
||||
<title>Stack</title>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M54.79,76.45h1.58L46,62l-1,.93Z" style="fill: #2a1659"/>
|
||||
<path d="M21.85,28.46H20.09l18.37,25.4c.27-.39.55-.77.83-1.16Z" style="fill: #2a1659"/>
|
||||
<path d="M25.32,28.46H23.57l16.61,23L41,50.32Z" style="fill: #2a1659"/>
|
||||
<path d="M58.23,76.45h1.59L48,60l-1,.91Z" style="fill: #2a1659"/>
|
||||
<path d="M62.42,76.45h9.76L55.7,53.51c-2.11,1.65-4.16,3.35-6.13,5.11Z" style="fill: #2a1659"/>
|
||||
<path d="M37.71,28.46H27.84L42.35,48.59c1.68-2.16,3.45-4.26,5.28-6.31Z" style="fill: #2a1659"/>
|
||||
</g>
|
||||
<path d="M95.13,33.36a47.16,47.16,0,0,1,3.3,16.91A48.89,48.89,0,0,1,86.49,82.59,48.41,48.41,0,0,1,37.76,97.86a48.36,48.36,0,0,1-16.31-7.51A50.18,50.18,0,0,1,.78,43.09a50.13,50.13,0,0,1,16.49-31,48.71,48.71,0,0,1,15.2-9.13A47.38,47.38,0,0,1,49.84,0,46.31,46.31,0,0,1,81.36,12.87,47.3,47.3,0,0,0,49.86,2.46,45.08,45.08,0,0,0,33.67,6a46.59,46.59,0,0,0-13.78,9,47.76,47.76,0,0,0-9.76,13.11,46.27,46.27,0,0,0,2.93,46.63,45.72,45.72,0,0,0,11.22,11.7A44.9,44.9,0,0,0,39,93.29a45.78,45.78,0,0,0,31.92-3.08,47.32,47.32,0,0,0,22.3-23.67,49.09,49.09,0,0,0,3.88-16.31A49.59,49.59,0,0,0,95.13,33.36Z" style="fill: #2a1659"/>
|
||||
<g>
|
||||
<path d="M30.3,75.44c.75-1.34,1.45-2.57,2.11-3.72C31.68,73,31,74.19,30.3,75.44Z" style="fill: none"/>
|
||||
<path d="M95.09,12.49l0-.05h-.13S95,12.44,95.09,12.49Z" style="fill: #9eb3e5"/>
|
||||
<path d="M36.1,66.39a97.62,97.62,0,0,0-5.8,9c.67-1.25,1.38-2.49,2.11-3.72h0c1.56-2.64,3.26-5.23,5.07-7.78h0c15.24-21.36,37.74-38.09,59.39-46l-1.78-5.45c-.07-.05-.14-.08-.17-.05-30.49,11-58.66,39.46-68.5,71.15.48-1.16,1-2.31,1.53-3.46C42.06,57,69.19,38.07,94.45,29.81l-.75-5.18C71.48,31.61,50.08,47,36.1,66.39Z" style="fill: #6536ff"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M10.82,107.44,6.29,118.21H4.55L0,107.44H1.61l3.8,9.3,3.8-9.3Z" style="fill: #2a1659"/>
|
||||
<path d="M21.25,107.44v1.2h-6v2.3h-1.4v-3.5Zm-.11,5.87H13.87v-1.2h7.27ZM15.27,117h6v1.2H13.87v-3.74h1.4Z" style="fill: #2a1659"/>
|
||||
<path d="M34.87,107.39l-8.79,10.82H24.3l8.79-10.82Zm-7.07,4.29-3.5-4.29h1.81l2.59,3.2Zm7.08,6.53H33.11L30.49,115l.89-1.1Z" style="fill: #2a1659"/>
|
||||
<path d="M48.5,107.39l-8.8,10.82H37.93l8.79-10.82Zm-7.07,4.29-3.5-4.29h1.81l2.59,3.2Zm7.08,6.53H46.74L44.12,115l.89-1.1Z" style="fill: #2a1659"/>
|
||||
<path d="M61,112.07v6.14H59.55v-4.94h-8v-5.83H53v4.63Zm-9.4,6.14v-3.77H53v3.77Zm8-7.3v-3.47H61v3.47Z" style="fill: #6536ff"/>
|
||||
<path d="M75.21,112.82a5.61,5.61,0,1,1-5.61-5.57A5.38,5.38,0,0,1,75.21,112.82Zm-1.45,0a4.16,4.16,0,1,0-4.16,4.37A4.08,4.08,0,0,0,73.76,112.82Z" style="fill: #6536ff"/>
|
||||
<path d="M86.75,115.23c0,1.56-1.12,3.17-4.16,3.17a5.74,5.74,0,0,1-4.33-1.71l.84-1a4.75,4.75,0,0,0,3.54,1.55c2,0,2.65-1,2.65-1.87,0-2.78-6.68-1.22-6.68-5.06,0-1.77,1.66-3,3.89-3a5.42,5.42,0,0,1,4,1.51l-.84,1a4.39,4.39,0,0,0-3.27-1.29c-1.33,0-2.31.7-2.31,1.71C80.07,112.6,86.75,111.21,86.75,115.23Z" style="fill: #6536ff"/>
|
||||
<path d="M89.78,108.64v-1.2h8.55v1.2Zm3.56,9.57v-8.4h1.41v8.4Z" style="fill: #6536ff"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
31
images/horizon/logo.svg
Normal file
31
images/horizon/logo.svg
Normal file
@ -0,0 +1,31 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 560.46 99.32">
|
||||
<title>Horizontal</title>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M172.92,28.88l-20.07,47.7h-7.72L125,28.88h7.11L149,70.06,165.8,28.88Z" style="fill: #2a1659"/>
|
||||
<path d="M219.12,28.88v5.31H192.61V44.38H186.4V28.88Zm-.52,26H186.4V49.55h32.2Zm-26,16.4h26.51v5.32H186.4V60h6.21Z" style="fill: #2a1659"/>
|
||||
<path d="M279.41,28.65,240.47,76.58H232.6l38.94-47.93Zm-31.31,19-15.5-19h8l11.46,14.16Zm31.38,28.91h-7.86L260,62.35l4-4.87Z" style="fill: #2a1659"/>
|
||||
<path d="M339.77,28.65,300.82,76.58H293L331.9,28.65Zm-31.31,19-15.5-19h8l11.46,14.16Zm31.38,28.91H332L320.37,62.35l4-4.87Z" style="fill: #2a1659"/>
|
||||
<path d="M395,49.4V76.58h-6.22V54.71H353.32V28.88h6.22V49.4ZM353.32,76.58V59.88h6.22v16.7Zm35.42-32.35V28.88H395V44.23Z" style="fill: #6536ff"/>
|
||||
<path d="M458.09,52.69c0,14.08-10.11,24.64-24.86,24.64s-24.79-10.56-24.79-24.64,10-24.64,24.79-24.64S458.09,38.61,458.09,52.69Zm-6.44,0c0-11.16-7.27-19.4-18.42-19.4s-18.35,8.24-18.35,19.4,7.11,19.4,18.35,19.4S451.65,63.77,451.65,52.69Z" style="fill: #6536ff"/>
|
||||
<path d="M509.16,63.4c0,6.89-4.94,14-18.42,14-8.61,0-15.05-3.14-19.17-7.56l3.74-4.57A20.94,20.94,0,0,0,491,72.16c8.91,0,11.75-4.57,11.75-8.31,0-12.28-29.58-5.39-29.58-22.39,0-7.87,7.34-13.33,17.23-13.33,7.56,0,13.48,2.47,17.67,6.66l-3.74,4.35c-3.75-4-9-5.7-14.46-5.7-5.91,0-10.26,3.07-10.26,7.57C479.58,51.72,509.16,45.58,509.16,63.4Z" style="fill: #6536ff"/>
|
||||
<path d="M522.57,34.19V28.88h37.89v5.31Zm15.8,42.39V39.36h6.21V76.58Z" style="fill: #6536ff"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M54.39,76.45H56L45.55,62l-.95.93Z" style="fill: #2a1659"/>
|
||||
<path d="M21.45,28.46H19.69l18.37,25.4c.27-.39.55-.77.83-1.16Z" style="fill: #2a1659"/>
|
||||
<path d="M24.92,28.46H23.17l16.61,23,.85-1.13Z" style="fill: #2a1659"/>
|
||||
<path d="M57.83,76.45h1.59L47.61,60l-1,.91Z" style="fill: #2a1659"/>
|
||||
<path d="M62,76.45h9.75L55.3,53.51c-2.11,1.65-4.16,3.35-6.13,5.11Z" style="fill: #2a1659"/>
|
||||
<path d="M37.31,28.46H27.44L42,48.59c1.68-2.16,3.45-4.26,5.28-6.31Z" style="fill: #2a1659"/>
|
||||
</g>
|
||||
<path d="M94.73,33.36A47.16,47.16,0,0,1,98,50.27,48.89,48.89,0,0,1,86.09,82.59,48.41,48.41,0,0,1,37.36,97.86a48.36,48.36,0,0,1-16.31-7.51A50.18,50.18,0,0,1,.38,43.09a50.13,50.13,0,0,1,16.49-31,48.71,48.71,0,0,1,15.2-9.13A47.38,47.38,0,0,1,49.44,0,46.31,46.31,0,0,1,81,12.87,47.3,47.3,0,0,0,49.46,2.46,45.08,45.08,0,0,0,33.27,6a46.59,46.59,0,0,0-13.78,9A47.76,47.76,0,0,0,9.73,28.05a46.27,46.27,0,0,0,2.93,46.63,45.72,45.72,0,0,0,11.22,11.7,44.9,44.9,0,0,0,14.67,6.91,45.78,45.78,0,0,0,31.92-3.08A47.25,47.25,0,0,0,92.76,66.54a48.86,48.86,0,0,0,3.89-16.31A49.59,49.59,0,0,0,94.73,33.36Z" style="fill: #2a1659"/>
|
||||
<g>
|
||||
<path d="M29.9,75.44c.75-1.34,1.45-2.57,2.11-3.72C31.28,73,30.57,74.19,29.9,75.44Z" style="fill: none"/>
|
||||
<path d="M94.69,12.49l0-.05h-.13S94.61,12.44,94.69,12.49Z" style="fill: #9eb3e5"/>
|
||||
<path d="M35.7,66.39a95.58,95.58,0,0,0-5.8,9c.67-1.25,1.38-2.49,2.11-3.72h0c1.56-2.64,3.26-5.23,5.07-7.78h0c15.24-21.36,37.74-38.09,59.39-46l-1.78-5.45c-.08-.05-.14-.08-.17-.05C64,23.48,35.86,51.9,26,83.59c.48-1.16,1-2.31,1.53-3.46C41.66,57,68.79,38.07,94.05,29.81l-.75-5.18C71.08,31.61,49.68,47,35.7,66.39Z" style="fill: #6536ff"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
9
images/horizon/manage.py
Normal file
9
images/horizon/manage.py
Normal file
@ -0,0 +1,9 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
|
||||
"openstack_dashboard.settings")
|
||||
execute_from_command_line(sys.argv)
|
81
openstack_operator/horizon.py
Normal file
81
openstack_operator/horizon.py
Normal file
@ -0,0 +1,81 @@
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""horizon Operator
|
||||
|
||||
This module maintains the operator for Mcrouter, it takes care of creating
|
||||
the appropriate deployments, Mcrouter, pod monitors and Prometheus rules.
|
||||
"""
|
||||
|
||||
import kopf
|
||||
|
||||
from openstack_operator import utils
|
||||
|
||||
|
||||
@kopf.on.create('dashboard.openstack.org', 'v1alpha1', 'horizons')
|
||||
def create_secret(name, **_):
|
||||
"""Create a new horizon secret"""
|
||||
|
||||
utils.create_or_update('horizon/secret-secretkey.yml.j2',
|
||||
name=name,
|
||||
secret=utils.generate_password())
|
||||
|
||||
|
||||
@kopf.on.resume('dashboard.openstack.org', 'v1alpha1', 'horizons')
|
||||
@kopf.on.create('dashboard.openstack.org', 'v1alpha1', 'horizons')
|
||||
def create_or_resume(namespace, name, spec, **_):
|
||||
"""Create and re-sync a horizon instance
|
||||
|
||||
This function is called when a new resource is created but also when we
|
||||
start the service up for the first time.
|
||||
"""
|
||||
|
||||
# Grab the secretkey secret
|
||||
secret_key = utils.get_secret(namespace, "horizon-%s-secretkey" % name)
|
||||
utils.create_or_update('horizon/secret-config.yml.j2',
|
||||
name=name,
|
||||
secret=secret_key['secret_key'])
|
||||
conn = utils.get_openstack_connection()
|
||||
auth_url = conn.config.auth["auth_url"]
|
||||
config = utils.create_or_update('horizon/configmap.yml.j2',
|
||||
name=name, spec=spec, auth_url=auth_url)
|
||||
config_hash = utils.generate_hash(config.obj['data'])
|
||||
utils.create_or_update('horizon/deployment.yml.j2',
|
||||
config_hash=config_hash, name=name, spec=spec)
|
||||
utils.create_or_update('horizon/service.yml.j2',
|
||||
name=name, spec=spec)
|
||||
utils.create_or_update('horizon/memcached.yml.j2',
|
||||
name=name, spec=spec)
|
||||
if "ingress" in spec:
|
||||
utils.create_or_update('horizon/ingress.yml.j2',
|
||||
name=name, spec=spec)
|
||||
|
||||
|
||||
@kopf.on.update('dashboard.openstack.org', 'v1alpha1', 'horizons')
|
||||
def update(name, spec, **_):
|
||||
"""Update a horizon
|
||||
|
||||
This function updates the deployment for horizon if there are any
|
||||
changes that happen within it.
|
||||
"""
|
||||
conn = utils.get_openstack_connection()
|
||||
auth_url = conn.config.auth["auth_url"]
|
||||
config = utils.create_or_update('horizon/configmap.yml.j2',
|
||||
name=name, spec=spec, auth_url=auth_url)
|
||||
config_hash = utils.generate_hash(config.obj['data'])
|
||||
utils.create_or_update('horizon/deployment.yml.j2',
|
||||
config_hash=config_hash, name=name, spec=spec)
|
||||
if hasattr(spec, "ingress"):
|
||||
utils.create_or_update('horizon/ingress.yml.j2',
|
||||
name=name, spec=spec)
|
@ -24,8 +24,10 @@ from combinations of apiVersion and kind to the exact model.
|
||||
|
||||
from pykube.objects import ConfigMap
|
||||
from pykube.objects import Deployment
|
||||
from pykube.objects import Ingress
|
||||
from pykube.objects import NamespacedAPIObject
|
||||
from pykube.objects import Pod
|
||||
from pykube.objects import Secret
|
||||
from pykube.objects import Service
|
||||
from pykube.objects import StatefulSet
|
||||
|
||||
@ -38,6 +40,14 @@ class Mcrouter(NamespacedAPIObject):
|
||||
kind = "Mcrouter"
|
||||
|
||||
|
||||
class Memcached(NamespacedAPIObject):
|
||||
"""Memcached Kubernetes object"""
|
||||
|
||||
version = "infrastructure.vexxhost.cloud/v1alpha1"
|
||||
endpoint = "memcacheds"
|
||||
kind = "Memcached"
|
||||
|
||||
|
||||
class PodMonitor(NamespacedAPIObject):
|
||||
"""PodMonitor Kubernetes object"""
|
||||
|
||||
@ -58,14 +68,19 @@ MAPPING = {
|
||||
"v1": {
|
||||
"ConfigMap": ConfigMap,
|
||||
"Pod": Pod,
|
||||
"Secret": Secret,
|
||||
"Service": Service,
|
||||
},
|
||||
"apps/v1": {
|
||||
"Deployment": Deployment,
|
||||
"StatefulSet": StatefulSet,
|
||||
},
|
||||
"extensions/v1beta1": {
|
||||
"Ingress": Ingress
|
||||
},
|
||||
"infrastructure.vexxhost.cloud/v1alpha1": {
|
||||
"Mcrouter": Mcrouter,
|
||||
"Memcached": Memcached
|
||||
},
|
||||
"monitoring.coreos.com/v1": {
|
||||
"PodMonitor": PodMonitor,
|
||||
|
39
openstack_operator/templates/horizon/configmap.yml.j2
Normal file
39
openstack_operator/templates/horizon/configmap.yml.j2
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: horizon-{{ name }}
|
||||
namespace: default
|
||||
data:
|
||||
local_settings.py: |
|
||||
import os
|
||||
from openstack_dashboard.settings import HORIZON_CONFIG
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
SECRET_KEY = os.getenv('SECRET_KEY')
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||
'LOCATION': 'mcrouter-memcached-horizon-{{ name }}:11211',
|
||||
},
|
||||
}
|
||||
|
||||
OPENSTACK_KEYSTONE_URL = '{{ auth_url }}'
|
||||
|
||||
OPENSTACK_NEUTRON_NETWORK['enable_ha_router'] = True
|
79
openstack_operator/templates/horizon/deployment.yml.j2
Normal file
79
openstack_operator/templates/horizon/deployment.yml.j2
Normal file
@ -0,0 +1,79 @@
|
||||
---
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: horizon-{{ name }}
|
||||
labels:
|
||||
{{ labels("horizon", name) | indent(4) }}
|
||||
annotations:
|
||||
checksum/config: "{{ config_hash }}"
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
{{ labels("horizon", name) | indent(6) }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{ labels("horizon", name) | indent(8) }}
|
||||
spec:
|
||||
containers:
|
||||
- name: horizon
|
||||
image: vexxhost/horizon:latest
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: secret_key
|
||||
name: horizon-{{ name }}
|
||||
ports:
|
||||
- name: horizon
|
||||
containerPort: 8000
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: horizon
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: horizon
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
ephemeral-storage: 500M
|
||||
memory: 256M
|
||||
requests:
|
||||
cpu: 500m
|
||||
ephemeral-storage: 500M
|
||||
memory: 128M
|
||||
securityContext:
|
||||
runAsUser: 1001
|
||||
volumeMounts:
|
||||
- mountPath: /etc/horizon
|
||||
name: config
|
||||
volumes:
|
||||
- configMap:
|
||||
defaultMode: 420
|
||||
name: horizon-{{ name }}
|
||||
name: config
|
||||
{% if 'nodeSelector' in spec %}
|
||||
nodeSelector:
|
||||
{{ spec.nodeSelector | to_yaml | indent(8) }}
|
||||
{% endif %}
|
||||
{% if 'tolerations' in spec %}
|
||||
tolerations:
|
||||
{{ spec.tolerations | to_yaml | indent(8) }}
|
||||
{% endif %}
|
28
openstack_operator/templates/horizon/ingress.yml.j2
Normal file
28
openstack_operator/templates/horizon/ingress.yml.j2
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: horizon-{{ name }}
|
||||
spec:
|
||||
rules:
|
||||
- host: {{ spec.ingress.host }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: horizon-{{ name }}
|
||||
servicePort: 80
|
23
openstack_operator/templates/horizon/memcached.yml.j2
Normal file
23
openstack_operator/templates/horizon/memcached.yml.j2
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: infrastructure.vexxhost.cloud/v1alpha1
|
||||
kind: Memcached
|
||||
metadata:
|
||||
name: horizon-{{ name }}
|
||||
labels:
|
||||
{{ labels("horizon", name) | indent(4) }}
|
||||
spec:
|
||||
megabytes: 128
|
21
openstack_operator/templates/horizon/secret-config.yml.j2
Normal file
21
openstack_operator/templates/horizon/secret-config.yml.j2
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: horizon-{{ name }}
|
||||
stringData:
|
||||
secret_key: {{ secret }}
|
21
openstack_operator/templates/horizon/secret-secretkey.yml.j2
Normal file
21
openstack_operator/templates/horizon/secret-secretkey.yml.j2
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: horizon-{{ name }}-secretkey
|
||||
stringData:
|
||||
secret_key: {{ secret }}
|
28
openstack_operator/templates/horizon/service.yml.j2
Normal file
28
openstack_operator/templates/horizon/service.yml.j2
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: horizon-{{ name }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: horizon
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: horizon
|
||||
selector:
|
||||
{{ labels("horizon", name) | indent(4) }}
|
@ -34,7 +34,6 @@ class KubernetesObjectTestCase(testtools.TestCase):
|
||||
SAMPLES_PATH = 'config/samples'
|
||||
SAMPLE_FILE = ''
|
||||
TEMPLATE_FILE = ''
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
sample_path = "%s/%s" % (cls.SAMPLES_PATH, cls.SAMPLE_FILE)
|
||||
|
27
openstack_operator/tests/unit/test_horizon.py
Normal file
27
openstack_operator/tests/unit/test_horizon.py
Normal file
@ -0,0 +1,27 @@
|
||||
# Copyright 2020 VEXXHOST, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Tests for Horizon Operator
|
||||
|
||||
This module contains all the tests for the Horizon operator.
|
||||
"""
|
||||
|
||||
from openstack_operator.tests.unit import base
|
||||
|
||||
|
||||
class HorizonDeploymentTestCase(base.DeploymentTestCase):
|
||||
"""Basic tests for the Deployment."""
|
||||
|
||||
SAMPLE_FILE = 'dashboard_v1alpha1_horizon.yaml'
|
||||
TEMPLATE_FILE = 'horizon/deployment.yml.j2'
|
@ -17,17 +17,19 @@
|
||||
The module contains a few useful utilities which we refactor out in order
|
||||
to be able to use them across all different operators.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import copy
|
||||
import operator
|
||||
import os
|
||||
import secrets
|
||||
import string
|
||||
|
||||
import jinja2
|
||||
import openstack
|
||||
import kopf
|
||||
from pbr import version
|
||||
import pykube
|
||||
import yaml
|
||||
import openstack
|
||||
|
||||
from openstack_operator import objects
|
||||
|
||||
@ -41,6 +43,11 @@ def to_yaml(value):
|
||||
return yaml.safe_dump(value)
|
||||
|
||||
|
||||
def to_dict(value):
|
||||
"""Return a dictionary from a YAML string"""
|
||||
return yaml.safe_load(value)
|
||||
|
||||
|
||||
def labels(app, instance, component=None):
|
||||
"""Return standard labels for the operator."""
|
||||
metadata = {
|
||||
@ -82,6 +89,8 @@ def create_or_update(template, **kwargs):
|
||||
raise
|
||||
resource.create()
|
||||
|
||||
return resource
|
||||
|
||||
|
||||
def ensure_absent(template, **kwargs):
|
||||
"""Ensure a Kubernetes resource bound to a template is deleted
|
||||
@ -156,3 +165,37 @@ def get_openstack_connection():
|
||||
"""Get an instance of OpenStack SDK."""
|
||||
return openstack.connect(cloud="envvars", app_name='openstack-operator',
|
||||
app_version=VERSION)
|
||||
|
||||
|
||||
def generate_password(length=20):
|
||||
"""Generate a random password."""
|
||||
|
||||
alphabet = string.ascii_letters + string.digits
|
||||
return ''.join(secrets.choice(alphabet) for i in range(length))
|
||||
|
||||
|
||||
def get_secret(namespace, name):
|
||||
"""Retrieve a secret from Kubernetes.
|
||||
|
||||
This function retrieves a Secret from Kubernetes, decodes it and passes
|
||||
the value of the data
|
||||
"""
|
||||
|
||||
api = pykube.HTTPClient(pykube.KubeConfig.from_env())
|
||||
secret = objects.Secret.objects(api).get(
|
||||
namespace=namespace,
|
||||
name=name
|
||||
)
|
||||
|
||||
return {
|
||||
k: base64.b64decode(v).decode('utf-8')
|
||||
for k, v in secret.obj['data'].items()
|
||||
}
|
||||
|
||||
|
||||
def generate_hash(dictionary):
|
||||
"""Generate a has from a dictionary, return None if dictionary is empty"""
|
||||
|
||||
if not dictionary:
|
||||
return None
|
||||
return hash(frozenset(dictionary.items()))
|
||||
|
@ -20,33 +20,37 @@
|
||||
jobs:
|
||||
- openstack-operator:functional:
|
||||
dependencies:
|
||||
- name: openstack-operator:images:build:ceilometer
|
||||
- name: openstack-operator:images:build:mcrouter-exporter
|
||||
soft: true
|
||||
- name: openstack-operator:images:build:horizon
|
||||
soft: true
|
||||
- name: openstack-operator:images:build:rabbitmq
|
||||
soft: true
|
||||
- name: openstack-operator:images:build:ceilometer
|
||||
soft: true
|
||||
- name: openstack-operator:images:build:memcached-exporter
|
||||
soft: true
|
||||
- name: openstack-operator:images:build:memcached
|
||||
soft: true
|
||||
- name: openstack-operator:images:build:mcrouter
|
||||
soft: true
|
||||
- openstack-operator:images:build:openstack-operator
|
||||
- name: openstack-operator:images:build:mcrouter-exporter
|
||||
soft: true
|
||||
- name: openstack-operator:images:build:memcached-exporter
|
||||
soft: true
|
||||
gate:
|
||||
jobs:
|
||||
- openstack-operator:functional:
|
||||
dependencies:
|
||||
- name: openstack-operator:images:upload:ceilometer
|
||||
- name: openstack-operator:images:upload:mcrouter-exporter
|
||||
soft: true
|
||||
- name: openstack-operator:images:upload:horizon
|
||||
soft: true
|
||||
- name: openstack-operator:images:upload:rabbitmq
|
||||
soft: true
|
||||
- name: openstack-operator:images:upload:ceilometer
|
||||
soft: true
|
||||
- name: openstack-operator:images:upload:memcached-exporter
|
||||
soft: true
|
||||
- name: openstack-operator:images:upload:memcached
|
||||
soft: true
|
||||
- name: openstack-operator:images:upload:mcrouter
|
||||
soft: true
|
||||
- openstack-operator:images:upload:openstack-operator
|
||||
- name: openstack-operator:images:upload:mcrouter-exporter
|
||||
soft: true
|
||||
- name: openstack-operator:images:upload:memcached-exporter
|
||||
soft: true
|
||||
|
31
zuul.d/horizon-jobs.yaml
Normal file
31
zuul.d/horizon-jobs.yaml
Normal file
@ -0,0 +1,31 @@
|
||||
- job:
|
||||
name: openstack-operator:images:build:horizon
|
||||
parent: vexxhost-build-docker-image
|
||||
provides: openstack-operator:image:horizon
|
||||
vars: &id001
|
||||
docker_images:
|
||||
- context: images/horizon
|
||||
repository: vexxhost/horizon
|
||||
files: &id002
|
||||
- ^images/horizon/.*
|
||||
- job:
|
||||
name: openstack-operator:images:upload:horizon
|
||||
parent: vexxhost-upload-docker-image
|
||||
provides: openstack-operator:image:horizon
|
||||
vars: *id001
|
||||
files: *id002
|
||||
- job:
|
||||
name: openstack-operator:images:promote:horizon
|
||||
parent: vexxhost-promote-docker-image
|
||||
vars: *id001
|
||||
files: *id002
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- openstack-operator:images:build:horizon
|
||||
gate:
|
||||
jobs:
|
||||
- openstack-operator:images:upload:horizon
|
||||
promote:
|
||||
jobs:
|
||||
- openstack-operator:images:promote:horizon
|
Loading…
x
Reference in New Issue
Block a user