Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugins support #21

Merged
merged 7 commits into from
Nov 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env.dist
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# will not allow container to exit even if application exits
VERSION=4.2.7
VERSION=4.2.14
DEBUG=false

# http settings domain, scheme
TAIGA_HOSTNAME=taiga.localhost
TAIGA_SCHEME=http
TAIGA_PLUGINS=slack

# general
TAIGA_SECRET_KEY=PLEASE-CHANGE-ME
Expand Down
33 changes: 22 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ ENV DEBIAN_FRONTEND=noninteractive \
TAIGA_ENABLE_EVENTS=false \
# Hostname for events server
TAIGA_EVENTS_HOST=events \
# Should Taiga automatically redirect to SSL version of Taiga?
TAIGA_REDIRECT_TO_SSL=false \
# Hostname of your instance (domain ex. riotkit.org or subdomain - board.riotkit.org)
TAIGA_HOSTNAME=localhost \
# Set to `true` to enable the LDAP authentication.
Expand Down Expand Up @@ -108,17 +106,29 @@ ENV DEBIAN_FRONTEND=noninteractive \
TAIGA_IMPORTER_ASANA_APP_SECRET="" \
DEBUG=false \
TAIGA_UID=1000 \
TAIGA_GID=1000
TAIGA_GID=1000 \
# List of plugins to enable eg. "slack, other, other" or just "slack"
TAIGA_PLUGINS=""

COPY bin/plugins/plugin-manager.py /opt/riotkit/bin/plugin-manager.py
COPY plugins /usr/src/taiga-plugins

# install dependencies
# download and unpack applications in selected versions
# set a locale
# clean up
RUN set -x \
&& apt-get update \
&& apt-get install -y --no-install-recommends locales gettext ca-certificates nginx libcap2-bin supervisor wget curl \
&& apt-get install -y --no-install-recommends locales gettext ca-certificates nginx libcap2-bin supervisor wget curl subversion \
&& apt-get clean \
\
&& echo "LANG=en_US.UTF-8" > /etc/default/locale \
&& echo "LC_TYPE=en_US.UTF-8" > /etc/default/locale \
&& echo "LC_MESSAGES=POSIX" >> /etc/default/locale \
&& echo "LANGUAGE=en" >> /etc/default/locale \
&& locale-gen en_US.UTF-8 && dpkg-reconfigure locales \
&& locale -a \
\
&& addgroup --gid $TAIGA_GID taiga \
&& adduser taiga --uid $TAIGA_UID --home /usr/src --disabled-password --shell /bin/bash --gid $TAIGA_GID \
&& setcap cap_net_bind_service=ep /usr/sbin/nginx \
Expand All @@ -136,16 +146,14 @@ RUN set -x \
\
&& rm /usr/src/*.tar.gz \
\
&& mkdir -p /taiga /usr/src/taiga-front-dist/dist/js/ \
&& mkdir -p /taiga /usr/src/taiga-front-dist/dist/js/ /usr/src/taiga-front-dist/dist/plugins \
&& pip install --no-cache-dir -r /usr/src/taiga-back/requirements.txt \
&& pip install --no-cache-dir j2cli \
&& pip install --no-cache-dir taiga-contrib-ldap-auth-ext \
&& echo "LANG=en_US.UTF-8" > /etc/default/locale \
&& echo "LC_TYPE=en_US.UTF-8" > /etc/default/locale \
&& echo "LC_MESSAGES=POSIX" >> /etc/default/locale \
&& echo "LANGUAGE=en" >> /etc/default/locale \
&& locale-gen en_US.UTF-8 && dpkg-reconfigure locales \
&& locale -a
&& chmod +x /opt/riotkit/bin/* \
&& mkdir -p /usr/src/taiga-plugins \
&& /opt/riotkit/bin/plugin-manager.py install-all-plugins


# Configure SSL ( Required for the LDAP plugin )
RUN echo "CipherString=DEFAULT@SECLEVEL=1" >> /etc/ssl/openssl.cnf
Expand All @@ -161,6 +169,9 @@ RUN cp /opt/taiga-conf/taiga/local.py /usr/src/taiga-back/settings/local.py \
&& cp /opt/taiga-conf/taiga/docker-settings.py /usr/src/taiga-back/settings/docker.py \
&& j2 /opt/taiga-conf/locale.gen.j2 > /etc/locale.gen \
\
# NOTICE: In case that "collectstatic" would not be found, it means in Django that the Taiga was not loaded
# and only basic Django application is configured because of an error, so Taiga commands are not loaded in that case
\
&& cd /usr/src/taiga-back/ && python manage.py collectstatic --noinput \
&& mkdir -p /var/log/nginx /var/lib/nginx \
&& touch /var/run/nginx.pid
Expand Down
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ _prepare_env:
### CI

build_image: ## Build the image (params: VERSION, VERSION_FRONT)
${SUDO} docker build . -f Dockerfile \
version_front=${VERSION_FRONT};
version_front=$${version_front:-${VERSION}}; \
\
set -x; ${SUDO} docker build . -f Dockerfile \
--build-arg TAIGA_BACK_VERSION=${VERSION} \
--build-arg TAIGA_FRONT_VERSION=${VERSION_FRONT}${VERSION_FRONT_SUFFIX} \
--build-arg TAIGA_FRONT_VERSION=$${version_front}${VERSION_FRONT_SUFFIX} \
-t quay.io/riotkit/taiga:${VERSION}

push_image: ## Push the image to the registry (params: VERSION, GIT_TAG)
Expand Down Expand Up @@ -89,7 +92,7 @@ ci@all: _download_tools ## Build all recent versions from github (Params: GIT_TA
RELEASE_TAG_TEMPLATE="%MATCH_0%-b${GIT_TAG}"; \
fi; \
fi; \
./.helpers/for-each-github-release --exec "make build_image push_image VERSION=%MATCH_0% VERSION_FRONT=%MATCH_0%-stable GIT_TAG=$$GIT_TAG" --repo-name taigaio/taiga-back --dest-docker-repo quay.io/riotkit/taiga $${BUILD_PARAMS}--allowed-tags-regexp="([0-9\.]+)$$" --release-tag-template="$${RELEASE_TAG_TEMPLATE}" --max-versions=5 --verbose
./.helpers/for-each-github-release --exec "make build_image push_image VERSION=%MATCH_0% VERSION_FRONT=%MATCH_0% GIT_TAG=$$GIT_TAG" --repo-name taigaio/taiga-back --dest-docker-repo quay.io/riotkit/taiga $${BUILD_PARAMS}--allowed-tags-regexp="([0-9\.]+)$$" --release-tag-template="$${RELEASE_TAG_TEMPLATE}" --max-versions=5 --verbose

_download_tools:
curl -s https://raw.githubusercontent.com/riotkit-org/ci-utils/${RIOTKIT_UTILS_VER}/bin/extract-envs-from-dockerfile > .helpers/extract-envs-from-dockerfile
Expand Down
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ make start
# tadam...
```

##### First log-in to the application, default username and password

To log-in first time you should go to the [login page](http://localhost/login?next=%252Fdiscover) and enter "admin" as username, and "123123" as password.
You can also log-in to the Django administration panel at http://localhost/admin/ (please remember about the slash at the end)

#### Configuring LDAP

LDAP support can optionally be enabled by setting the `TAIGA_LDAP` environment variable to `true`. See the Dockerfile for a list of the environment variables used for configuring LDAP and their descriptions.
Expand Down Expand Up @@ -141,9 +146,6 @@ List of all environment variables that could be used.
# Hostname for events server
- TAIGA_EVENTS_HOST # (default: events)

# Should Taiga automatically redirect to SSL version of Taiga?
- TAIGA_REDIRECT_TO_SSL # (default: false)

# Hostname of your instance (domain ex. riotkit.org or subdomain - board.riotkit.org)
- TAIGA_HOSTNAME # (default: localhost)

Expand Down Expand Up @@ -237,6 +239,9 @@ List of all environment variables that could be used.

- TAIGA_GID # (default: 1000)

# List of plugins to enable eg. "slack, other, other" or just "slack"
- TAIGA_PLUGINS # (default: "")


```

Expand Down
5 changes: 5 additions & 0 deletions README.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ make start
# tadam...
```

##### First log-in to the application, default username and password

To log-in first time you should go to the [login page](http://localhost/login?next=%252Fdiscover) and enter "admin" as username, and "123123" as password.
You can also log-in to the Django administration panel at http://localhost/admin/ (please remember about the slash at the end)

#### Configuring LDAP

LDAP support can optionally be enabled by setting the `TAIGA_LDAP` environment variable to `true`. See the Dockerfile for a list of the environment variables used for configuring LDAP and their descriptions.
Expand Down
144 changes: 144 additions & 0 deletions bin/plugins/plugin-manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/env python3

"""
Plugins management for RiotKit's container for Taiga.io application
===================================================================

Pre-installs all available plugins on container build,
then lets *ops to decide which plugin to enable on container startup

License: MIT
Author: RiotKit Collective (https://github.com/riotkit-org)
"""

import os
import sys
import json
import importlib.util


class PluginManager:
_front_path: str
_plugins_path: str
_plugins: dict

def __init__(self):
self._front_path = self._detect_front_path()
self._plugins_path = self._detect_plugins_path()
self._load_all()

def install(self):
"""
Command: Iterate over all AVAILABLE plugins and pre-install them. They can be enabled later.
:return:
"""

print(' >> Installing plugins...')
print(list(self._plugins.items()))

for plugin_name, module in self._plugins.items():
print(' >> Instaling plugin "%s"' % plugin_name)

os.chdir(self._front_path)
print(' .. installing frontend')
module.frontend_setup()

os.chdir('/usr/src/taiga-back/')
print(' .. installing backend')
module.backend_setup()

def after_application_migrations(self):
"""
Command: Execute code/commands after Taiga migration finishes (eg. execute plugin migrations)
:return:
"""

print(' >> Updating/migrating plugins...')
print(list(self._plugins.items()))

for plugin_name, module in self._plugins.items():
print(' >> Executing after_application_migration for plugin "%s"' % plugin_name)

os.chdir('/usr/src/taiga-back/')

if hasattr(module, 'after_application_migration'):
module.after_application_migration()

def export_plugin_variables_to_environment(self):
"""
Command: Enable SELECTED plugins
:return:
"""

enabled_plugins = os.getenv('TAIGA_PLUGINS', '').replace(' ', '').replace('"', '').strip().split(',')
valid_plugins_list = str(list(self._plugins.keys())).replace('.py', '')

frontend_contrib_plugins_list = []
backend_installed_apps = []

for enabled_plugin in enabled_plugins:
if not enabled_plugin:
continue

if enabled_plugin not in self._plugins:
raise Exception('Plugin name "%s" is invalid, valid options: %s' % (enabled_plugin, valid_plugins_list))

module = self._plugins[enabled_plugin]
frontend_contrib_plugins_list += module.FRONTEND_CONTRIB_PLUGINS
backend_installed_apps += module.BACKEND_INSTALLED_APPS

print('''
export FRONTEND_CONTRIB_PLUGINS_LIST="%s";
export BACKEND_INSTALLED_APPS="%s";
''' % (
json.dumps(frontend_contrib_plugins_list).strip('[]').replace('"', '\\"'),
json.dumps(backend_installed_apps).replace('"', '\\"')
)
)

def _load_all(self):
self._plugins = {}

for filename in os.scandir(self._plugins_path):
if not filename.name.endswith('.py'):
continue

plugin_name = os.path.basename(filename.name).replace('.py', '')
self._plugins[plugin_name] = self._load(plugin_name, filename.path)

@staticmethod
def _load(plugin_name: str, path: str):
spec = importlib.util.spec_from_file_location("dockertaiga.%s" % plugin_name, path)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)

return mod

@staticmethod
def _detect_plugins_path():
if os.path.isdir('/usr/src/taiga-plugins'):
return '/usr/src/taiga-plugins'

return os.path.abspath(os.path.dirname(__file__) + '/../../plugins/')

@staticmethod
def _detect_front_path():
if os.path.isdir('/usr/src/taiga-front-dist/dist/plugins'):
return '/usr/src/taiga-front-dist/dist/plugins'

return '/tmp'


if __name__ == '__main__':
action = sys.argv[1] if len(sys.argv) > 1 else ''
app = PluginManager()

if action == 'install-all-plugins':
app.install()
elif action == 'export':
app.export_plugin_variables_to_environment()
elif action == 'after-migrations':
app.after_application_migrations()
else:
print('Tasks: install-all-plugins, export')
sys.exit(1)
8 changes: 0 additions & 8 deletions conf/nginx/nginx.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@ http {
keepalive_timeout 65;
#gzip on;

{% if TAIGA_REDIRECT_TO_SSL.lower() == 'true' %}
server {
listen 80 default_server;
server_name _;
return 301 https://$server_name$request_uri;
}
{% endif %}

server {
listen 80 default_server;
server_name _;
Expand Down
4 changes: 3 additions & 1 deletion conf/taiga/conf.json.j2
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@
{% if TAIGA_IMPORTER_JIRA_ENABLED.lower() == 'true' %} {{ comma() }} "jira" {% endif %}
{% if TAIGA_IMPORTER_ASANA_ENABLED.lower() == 'true' %} {{ comma() }} "asana" {% endif %}
],
"contribPlugins": []
"contribPlugins": [
{{ FRONTEND_CONTRIB_PLUGINS_LIST }}
]
}
3 changes: 3 additions & 0 deletions conf/taiga/docker-settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# https://github.com/taigaio/taiga-back/blob/master/settings/common.py
from .common import *
import os
import json

DATABASES = {
'default': {
Expand Down Expand Up @@ -53,6 +54,8 @@
if os.getenv('TAIGA_LDAP', '').lower() == 'true':
INSTALLED_APPS += ['taiga_contrib_ldap_auth_ext']

INSTALLED_APPS += json.loads(os.getenv('BACKEND_INSTALLED_APPS', '[]'))

LDAP_SERVER = os.getenv('LDAP_SERVER', '')
LDAP_PORT = int(os.getenv('LDAP_PORT', 0))

Expand Down
2 changes: 2 additions & 0 deletions conf/taiga/local.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env python3

# If you want to modify this file, I recommend check out docker-taiga-example
# https://github.com/benhutchins/docker-taiga-example
#
Expand Down
Loading