diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/.travis.yml b/.travis.yml index 0509e49..99a0002 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: python -sudo: false +python: "3.6" +sudo: true services: - docker @@ -9,24 +10,25 @@ env: - secure: br4/uA6kM7/aiO9c4/uKrn0PCYHa8NTD/DV98N8K1/YHb5HGbOhIVrV7F7GBKiGOQKIwuD7hZ9fmZeI80iDjIdBfP+rlUt3Ipdd6/X+IwcHu46t9N89Fuw6EK+KApjK3et1BXvqT8GPMjOLX9a2O58fYMMr6OBPQGPDdSNCLnE7PQ1kX79WtXI/YpF3Ip5mDDrOeOOddVpS6+biHBthrdYRK/ZZJDTVt1HmL3Oe9LF8vt9Xw3JdzHnwBTuWg1mI+z0UCD7Nsylls/zxg8uORaMKnDIem9D9oIFWcLFWP9U/rqkIaoDi5XNwVWvMEmBT9D2qRfthm4yGyMFaBTbmE/JPG1bVuYgZYnz9DXRacRW978NudAYE7VOHjom89cW5sEt2525RbXtTgS53hZP+0PKwouXGvZPh+S45uSzKAuiCuXAuwRMLC9P77KKy+2ouhD0Czbz6BoBUtF8/KkTCQyxfo4h96+l3aVaCfD10LA3dRPJI2lWozvi57PmFvHVfKwN4B+aNunFvfuQhVdVZbudnKlFO0ew4AFaIZlKc35QeG8Yi7aymOeg+d2GsCpYG9blvMgF4+2K1Zt1OGbaO+cOhY3rI5pE6PRKQKfcpUaOLXhozLVBCMNJmXmbevuTwV6JK9UYnNRW7oVNfAbnox63PkfQIVC8LIJ7i21f/qjAU= - secure: Nwuuh9hk3JhmoPDQG5hCt5dOvQnwOQm0SkQsHbE9PHWMZSftysM/dig80qmdoB4JfcB+0OzXFPJwBZC+IMePzjEsGcP4p2BgEnYmDS3TrPcSiPAljqvOiNj/0/K7I74ZgLm4UtnRjM6m1Og4p8+ueOHXJIiOXMmd6O2njwFcrEk9zFOrYyNLCv6OfnOQDG8E9MFuV5uoHGyr4aurjdZNRj+Io6ENbatWBXCeFTh/XuDNDrCyBrB0FkRah2jF8JMi5hU+FQI78ZnXJxGhSabyEZhPRdPEPI2FHFSn3tEiaoRQghksIR9SNfz86HqZ488BBLttBPkl9m9TbXi9ZczjagkMS5mpQ5z2HNb0Jy5brlKVkfZQry/cmIoFZHWvNzUnCM6QzaQbmsinpC9BKdnllpQfRlE/Z4jzfVLeHCvOvJu8xrGj0LsVslJZTO2g2zZkbrH0myfiV3WHIKZW+IbblqtYIN3FlT8UMnK80TJKNqP1FYU4TAg15ZNtxcr9DTi4ybLm7+c4s+Blb3UNDzhP2IfUSLnLSs/5mPhXsg+CQXAYX6ZES50XH5HCLDPUsodfI1uVEyisOKYGyFh1/ggpXJagGCAc1b9DIAriYs347fZc1OrplUtzDFQmxEpW5kGlnC3vdfALYOTejUZX2OLWLJ1rfRhfcwoWOXc++T8lqvY= matrix: - - VERSION=0.9-composable - VERSION=1.0-composable - VERSION=1.1-composable - - VERSION=latest-composable + - VERSION=1.2 + - VERSION=dev + - VERSION=latest before_script: + - pip install sh requests docker-compose - cd ${VERSION} - - cp ../hub-docs/docker-compose.yml ../hub-docs/nginx.conf . - - sed -i 's/latest-composable/${VERSION}/' docker-compose.yml script: - set -e - docker build -t fiware/wirecloud:${VERSION} . - - docker-compose up -d - - sleep 40 - - curl -v http://localhost/api/version + # We need to run this using sudo to be able to remove some files created by + # docker + - sudo /home/travis/virtualenv/python3.6/bin/python tests.py after_success: + - set +e - test "$TRAVIS_BRANCH" = "master" && test "$TRAVIS_PULL_REQUEST" = "false" && docker login -u $DOCKER_USER -p $DOCKER_PASS && docker push fiware/wirecloud:${VERSION} branches: diff --git a/0.9-composable/Dockerfile b/0.9-composable/Dockerfile deleted file mode 100644 index 0249f61..0000000 --- a/0.9-composable/Dockerfile +++ /dev/null @@ -1,57 +0,0 @@ -FROM python:2-stretch - -MAINTAINER WireCloud Team - -WORKDIR /opt - -RUN apt update && \ - apt install -y libmemcached-dev && \ - pip install --no-cache-dir "python-social-auth<0.3,>=0.2.2" && \ - rm -rf /var/lib/apt/lists/* && \ - \ - export dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" && \ - wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.10/gosu-$dpkgArch" && \ - wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.10/gosu-$dpkgArch.asc" && \ - export GNUPGHOME="$(mktemp -d)" && \ - for server in $(shuf -e ha.pool.sks-keyservers.net \ - hkp://p80.pool.sks-keyservers.net:80 \ - keyserver.ubuntu.com \ - hkp://keyserver.ubuntu.com:80 \ - pgp.mit.edu) ; do \ - gpg --keyserver "$server" --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && break || : ; \ - done && \ - gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu && \ - rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc && \ - chmod +x /usr/local/bin/gosu && \ - gosu nobody true - -RUN pip install --no-cache-dir "wirecloud<1.0" "gunicorn==19.3.0" "psycopg2==2.6" pylibmc - -RUN adduser --system --group --shell /bin/bash wirecloud && \ - wirecloud-admin startproject wirecloud_instance && \ - chown -R wirecloud:wirecloud wirecloud_instance && \ - chmod a+x wirecloud_instance/manage.py - -WORKDIR /opt/wirecloud_instance - -RUN sed -i "s/'ENGINE': 'django.db.backends.'/'ENGINE': 'django.db.backends.postgresql_psycopg2'/g" wirecloud_instance/settings.py && \ - sed -i "s/'NAME': ''/'NAME': 'postgres'/g" wirecloud_instance/settings.py && \ - sed -i "s/'USER': ''/'USER': 'postgres'/g" wirecloud_instance/settings.py && \ - sed -i "s/'PASSWORD': ''/'PASSWORD': 'postgres'/g" wirecloud_instance/settings.py && \ - sed -i "s/'HOST': ''/'HOST': 'postgres'/g" wirecloud_instance/settings.py && \ - sed -i "s/'PORT': ''/'PORT': '5432'/g" wirecloud_instance/settings.py && \ - sed -i "s/SECRET_KEY = '[^']\+'/SECRET_KEY = 'TOCHANGE_SECRET_KEY'/g" wirecloud_instance/settings.py && \ - sed -i "s/STATIC_ROOT = path.join(BASEDIR, '..\/static')/STATIC_ROOT = '\/var\/www\/static'/g" wirecloud_instance/settings.py - -RUN python manage.py collectstatic --noinput && \ - chown -R wirecloud:wirecloud /var/www/static - -# volumes must be created after running the collectstatic command -VOLUME /var/www/static -VOLUME /opt/wirecloud_instance - -EXPOSE 8000 - -COPY ./docker-entrypoint.sh / -COPY ./manage.py /usr/local/bin/ -ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/0.9-composable/apache-config.conf b/0.9-composable/apache-config.conf deleted file mode 100644 index 3f1202b..0000000 --- a/0.9-composable/apache-config.conf +++ /dev/null @@ -1,41 +0,0 @@ - - - - Require all granted - Order allow,deny - Allow from all - - - - - Options Indexes FollowSymLinks - AllowOverride None - Require all granted - - - ### Wirecloud ### - WSGIPassAuthorization On - - WSGIDaemonProcess wirecloud python-path=/opt/wirecloud_instance user=wirecloud group=wirecloud - WSGIScriptAlias / /opt/wirecloud_instance/wirecloud_instance/wsgi.py - - WSGIProcessGroup wirecloud - - - Alias /static /opt/wirecloud_instance/static - - SetHandler None - - ExpiresActive On - ExpiresDefault "access plus 1 week" - - - Header append Cache-Control "public" - - - - - ExpiresDefault "access plus 3 years" - - - diff --git a/0.9-composable/docker-entrypoint.sh b/0.9-composable/docker-entrypoint.sh deleted file mode 100755 index 9c9962b..0000000 --- a/0.9-composable/docker-entrypoint.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Wait DB to be accepting requests -exec 8<>/dev/tcp/postgres/5432 -DB_STATUS=$? - -i=0 - -while [[ ${DB_STATUS} -ne 0 && ${i} -lt 50 ]]; do - sleep 5 - exec 8<>/dev/tcp/postgres/5432 - DB_STATUS=$? - - i=${i}+1 -done - -# Check if we have to init wirecloud configuration -if [ ! -f /opt/wirecloud_instance/wirecloud_instance/settings.py ]; then - - cd /opt - - # Use the target_directory parameter to indicate that we want to use that - # directory even if it exit - wirecloud-admin startproject wirecloud_instance wirecloud_instance - chown -R wirecloud:wirecloud wirecloud_instance; \ - chmod a+x wirecloud_instance/manage.py - - cd /opt/wirecloud_instance - - sed -i "s/'ENGINE': 'django.db.backends.'/'ENGINE': 'django.db.backends.postgresql_psycopg2'/g" wirecloud_instance/settings.py; \ - sed -i "s/'NAME': ''/'NAME': 'postgres'/g" wirecloud_instance/settings.py; \ - sed -i "s/'USER': ''/'USER': 'postgres'/g" wirecloud_instance/settings.py; \ - sed -i "s/'PASSWORD': ''/'PASSWORD': 'postgres'/g" wirecloud_instance/settings.py; \ - sed -i "s/'HOST': ''/'HOST': 'postgres'/g" wirecloud_instance/settings.py; \ - sed -i "s/'PORT': ''/'PORT': '5432'/g" wirecloud_instance/settings.py; \ - sed -i "s/SECRET_KEY = '[^']\+'/SECRET_KEY = '$(python -c "from django.utils.crypto import get_random_string; import re; print(re.escape(get_random_string(50, 'abcdefghijklmnopqrstuvwxyz0123456789%^&*(-_=+)')))")'/g" wirecloud_instance/settings.py; \ - sed -i "s/STATIC_ROOT = path.join(BASEDIR, '..\/static')/STATIC_ROOT = '\/var\/www\/static'/g" wirecloud_instance/settings.py - - python manage.py collectstatic --noinput; \ - chown -R wirecloud:wirecloud /var/www/static - - python manage.py migrate --fake-initial - su wirecloud -c "python manage.py populate" -fi - -# allow the container to be started with `--user` -if [ "$(id -u)" = '0' ]; then - chown -R wirecloud . - chown -R wirecloud /var/www/static -fi - -# Real entry point -case "$1" in - initdb) - python manage.py migrate --fake-initial - ;; - createdefaultsuperuser) - echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'admin')" | python manage.py shell > /dev/null - ;; - createsuperuser) - python manage.py createsuperuser - ;; - *) - su wirecloud -c "/usr/local/bin/gunicorn wirecloud_instance.wsgi:application -w 2 -b :8000" - ;; -esac diff --git a/0.9/Dockerfile b/0.9/Dockerfile deleted file mode 100644 index 1a60868..0000000 --- a/0.9/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -FROM python:2 - -MAINTAINER WireCloud Team - -# Install apache2, social-auth and create a wirecloud user -RUN apt-get -y update && \ - apt-get install -y apache2 libapache2-mod-wsgi && \ - pip install --no-cache-dir "python-social-auth<0.3,>=0.2.2" && \ - adduser --system --group --shell /bin/bash wirecloud && \ - rm -rf /var/lib/apt/lists/* - -COPY ["apache-config.conf", "/etc/apache2/sites-enabled/000-default.conf"] - -WORKDIR /opt - -# Install WireCloud & dependencies -RUN pip install --no-cache-dir "wirecloud<0.10.0" - -RUN wirecloud-admin startproject wirecloud_instance --quick-start && \ - chown -R wirecloud:wirecloud wirecloud_instance - -WORKDIR /opt/wirecloud_instance -RUN sed -i "s/SECRET_KEY = '[^']\+'/SECRET_KEY = 'TOCHANGE_SECRET_KEY'/g" wirecloud_instance/settings.py - -# The volume must be created after running the wirecloud-admin command -VOLUME /opt/wirecloud_instance - -WORKDIR /opt/wirecloud_instance - -EXPOSE 80 - -COPY ./docker-entrypoint.sh / -ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/0.9/apache-config.conf b/0.9/apache-config.conf deleted file mode 100644 index 3f1202b..0000000 --- a/0.9/apache-config.conf +++ /dev/null @@ -1,41 +0,0 @@ - - - - Require all granted - Order allow,deny - Allow from all - - - - - Options Indexes FollowSymLinks - AllowOverride None - Require all granted - - - ### Wirecloud ### - WSGIPassAuthorization On - - WSGIDaemonProcess wirecloud python-path=/opt/wirecloud_instance user=wirecloud group=wirecloud - WSGIScriptAlias / /opt/wirecloud_instance/wirecloud_instance/wsgi.py - - WSGIProcessGroup wirecloud - - - Alias /static /opt/wirecloud_instance/static - - SetHandler None - - ExpiresActive On - ExpiresDefault "access plus 1 week" - - - Header append Cache-Control "public" - - - - - ExpiresDefault "access plus 3 years" - - - diff --git a/0.9/docker-entrypoint.sh b/0.9/docker-entrypoint.sh deleted file mode 100755 index f8f9cf2..0000000 --- a/0.9/docker-entrypoint.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -sed -i "s/SECRET_KEY = 'TOCHANGE_SECRET_KEY'/SECRET_KEY = '$(python -c "from django.utils.crypto import get_random_string; import re; print(re.escape(get_random_string(50, 'abcdefghijklmnopqrstuvwxyz0123456789%^&*(-_=+)')))")'/g" /opt/wirecloud_instance/wirecloud_instance/settings.py - -# Check if there are any pending migration -python manage.py migrate --fake-initial - -# Collect static files so we take into account custom themes and configurations -python manage.py collectstatic --noinput - -# Start apache processes in foreground -/usr/sbin/apache2ctl graceful-stop -rm -f /var/run/apache2/apache2.pid -exec /usr/sbin/apache2ctl -D FOREGROUND diff --git a/1.0-composable/docker-compose.yml b/1.0-composable/docker-compose.yml new file mode 100644 index 0000000..ea4f57d --- /dev/null +++ b/1.0-composable/docker-compose.yml @@ -0,0 +1,30 @@ +version: "3.1" + +services: + + nginx: + restart: always + image: nginx:latest + ports: + - 80:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./static:/var/www/static:ro + depends_on: + - wirecloud + + + postgres: + restart: always + image: postgres:latest + volumes: + - ./postgres-data:/var/lib/postgresql/data + + wirecloud: + restart: always + image: fiware/wirecloud:1.0-composable + depends_on: + - postgres + volumes: + - ./wirecloud_instance:/opt/wirecloud_instance + - ./static:/var/www/static diff --git a/dev-composable/nginx.conf b/1.0-composable/nginx.conf similarity index 100% rename from dev-composable/nginx.conf rename to 1.0-composable/nginx.conf diff --git a/1.0-composable/tests.py b/1.0-composable/tests.py new file mode 100644 index 0000000..2e7bf08 --- /dev/null +++ b/1.0-composable/tests.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. + +import os +import shutil +import time +import unittest +from urllib.parse import parse_qs, urlparse + +import requests +import sh + + +class ComposedTests(unittest.TestCase): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing composed test case") + print("#\n") + sh.docker_compose.up(d=True, remove_orphans=True, _fg=True) + time.sleep(40) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud_instance') + shutil.rmtree('postgres-data') + shutil.rmtree('static') + print() + + def test_features_api_should_be_available(self): + response = requests.get("http://localhost/api/features") + self.assertEqual(response.status_code, 200) + + def test_search_engine_should_work(self): + response = requests.get("http://localhost/api/search?namespace=workspace&maxresults=1") + self.assertEqual(response.status_code, 200) + + def test_root_page_should_work(self): + response = requests.get("http://localhost/") + self.assertEqual(response.status_code, 200) + + def test_home_page_should_work(self): + response = requests.get("http://localhost/wirecloud/home") + self.assertEqual(response.status_code, 200) + + def test_should_serve_static_files(self): + response = requests.get("http://localhost/static/theme/wirecloud.defaulttheme/images/logos/header.png") + self.assertEqual(response.status_code, 200) + + +if __name__ == "__main__": + unittest.main(verbosity=2) + diff --git a/1.1-composable/docker-compose.yml b/1.1-composable/docker-compose.yml new file mode 100644 index 0000000..adc349d --- /dev/null +++ b/1.1-composable/docker-compose.yml @@ -0,0 +1,30 @@ +version: "3.1" + +services: + + nginx: + restart: always + image: nginx:latest + ports: + - 80:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./static:/var/www/static:ro + depends_on: + - wirecloud + + + postgres: + restart: always + image: postgres:latest + volumes: + - ./postgres-data:/var/lib/postgresql/data + + wirecloud: + restart: always + image: fiware/wirecloud:1.1-composable + depends_on: + - postgres + volumes: + - ./wirecloud_instance:/opt/wirecloud_instance + - ./static:/var/www/static diff --git a/1.1-composable/nginx.conf b/1.1-composable/nginx.conf new file mode 100644 index 0000000..4debf13 --- /dev/null +++ b/1.1-composable/nginx.conf @@ -0,0 +1,49 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + server { + + listen 80; + server_name example.org; + client_max_body_size 20M; + charset utf-8; + + location /static { + alias /var/www/static; + } + + location / { + proxy_pass http://wirecloud:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + } +} diff --git a/1.1-composable/tests.py b/1.1-composable/tests.py new file mode 100644 index 0000000..2e7bf08 --- /dev/null +++ b/1.1-composable/tests.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. + +import os +import shutil +import time +import unittest +from urllib.parse import parse_qs, urlparse + +import requests +import sh + + +class ComposedTests(unittest.TestCase): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing composed test case") + print("#\n") + sh.docker_compose.up(d=True, remove_orphans=True, _fg=True) + time.sleep(40) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud_instance') + shutil.rmtree('postgres-data') + shutil.rmtree('static') + print() + + def test_features_api_should_be_available(self): + response = requests.get("http://localhost/api/features") + self.assertEqual(response.status_code, 200) + + def test_search_engine_should_work(self): + response = requests.get("http://localhost/api/search?namespace=workspace&maxresults=1") + self.assertEqual(response.status_code, 200) + + def test_root_page_should_work(self): + response = requests.get("http://localhost/") + self.assertEqual(response.status_code, 200) + + def test_home_page_should_work(self): + response = requests.get("http://localhost/wirecloud/home") + self.assertEqual(response.status_code, 200) + + def test_should_serve_static_files(self): + response = requests.get("http://localhost/static/theme/wirecloud.defaulttheme/images/logos/header.png") + self.assertEqual(response.status_code, 200) + + +if __name__ == "__main__": + unittest.main(verbosity=2) + diff --git a/dev-composable/.gitignore b/1.2/.gitignore similarity index 100% rename from dev-composable/.gitignore rename to 1.2/.gitignore diff --git a/dev-composable/Dockerfile b/1.2/Dockerfile similarity index 88% rename from dev-composable/Dockerfile rename to 1.2/Dockerfile index aed1bc9..cc51950 100644 --- a/dev-composable/Dockerfile +++ b/1.2/Dockerfile @@ -4,7 +4,7 @@ MAINTAINER WireCloud Team ENV DEFAULT_THEME=wirecloud.defaulttheme ENV FORWARDED_ALLOW_IPS=* -ENV DB_HOST=postgres +ENV DB_HOST= ENV DB_PORT=5432 RUN apt-get update && \ @@ -29,13 +29,7 @@ RUN apt-get update && \ gosu nobody true # Install WireCloud & dependencies -RUN git clone --depth=1 https://github.com/Wirecloud/wirecloud.git && \ - pip install "django<=1.11" && \ - cd wirecloud/src && \ - python setup.py bdist_wheel && \ - pip install --no-cache-dir dist/*.whl && \ - cd ../.. && \ - rm -rf wirecloud +RUN pip install --no-cache-dir "wirecloud<1.3" COPY ./docker-entrypoint.sh / COPY ./manage.py /usr/local/bin/ diff --git a/1.2/docker-compose-idm.yml b/1.2/docker-compose-idm.yml new file mode 100644 index 0000000..c13b7a5 --- /dev/null +++ b/1.2/docker-compose-idm.yml @@ -0,0 +1,77 @@ +version: "3" + +services: + + nginx: + restart: always + image: nginx:latest + ports: + - 80:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./wirecloud-static:/var/www/static:ro + depends_on: + - wirecloud + + + postgres: + restart: always + image: postgres:latest + environment: + - POSTGRES_PASSWORD=wirepass # Change this password! + volumes: + - ./postgres-data:/var/lib/postgresql/data + + + elasticsearch: + restart: always + image: elasticsearch:2.4 + volumes: + - ./elasticsearch-data:/usr/share/elasticsearch/data + command: elasticsearch -Des.index.max_result_window=50000 + + + memcached: + restart: always + image: memcached:1 + command: memcached -m 2048m + + + mysql: + restart: always + image: mysql/mysql-server:5.7.21 + environment: + - MYSQL_ROOT_PASSWORD=idm + - MYSQL_ROOT_HOST=% + + + keyrock: + restart: always + image: fiware/idm:7.0.2 + ports: + - 3000:3000 + environment: + - DATABASE_HOST=mysql + + + wirecloud: + restart: always + image: fiware/wirecloud:1.2 + depends_on: + - postgres + - elasticsearch + - memcached + environment: + - DEBUG=False + # - DEFAULT_THEME=wirecloud.defaulttheme + - DB_HOST=postgres + - DB_PASSWORD=wirepass # Change this password! + - FORWARDED_ALLOW_IPS=* + - ELASTICSEARCH2_URL=http://elasticsearch:9200/ + - MEMCACHED_LOCATION=memcached:11211 + - FIWARE_IDM_SERVER=${FIWARE_IDM_SERVER} + - SOCIAL_AUTH_FIWARE_KEY=${SOCIAL_AUTH_FIWARE_KEY} + - SOCIAL_AUTH_FIWARE_SECRET=${SOCIAL_AUTH_FIWARE_SECRET} + volumes: + - ./wirecloud-data:/opt/wirecloud_instance/data + - ./wirecloud-static:/var/www/static diff --git a/1.2/docker-compose-simple.yml b/1.2/docker-compose-simple.yml new file mode 100644 index 0000000..9f23b83 --- /dev/null +++ b/1.2/docker-compose-simple.yml @@ -0,0 +1,25 @@ +version: "3" + +services: + + nginx: + restart: always + image: nginx:latest + ports: + - 80:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./wirecloud-static:/var/www/static:ro + depends_on: + - wirecloud + + + wirecloud: + restart: always + image: fiware/wirecloud:1.2 + environment: + - DEBUG=False + - FORWARDED_ALLOW_IPS=* + volumes: + - ./wirecloud-data:/opt/wirecloud_instance/data + - ./wirecloud-static:/var/www/static diff --git a/1.2/docker-compose-standalone.yml b/1.2/docker-compose-standalone.yml new file mode 100644 index 0000000..08484fd --- /dev/null +++ b/1.2/docker-compose-standalone.yml @@ -0,0 +1,14 @@ +version: "3" + +services: + + wirecloud: + restart: always + image: fiware/wirecloud:1.2 + ports: + - 80:8000 + environment: + - DEBUG=True + volumes: + - ./wirecloud-data:/opt/wirecloud_instance/data + - ./wirecloud-static:/var/www/static diff --git a/dev-composable/docker-compose.yml b/1.2/docker-compose.yml similarity index 84% rename from dev-composable/docker-compose.yml rename to 1.2/docker-compose.yml index e334a39..91cfbed 100644 --- a/dev-composable/docker-compose.yml +++ b/1.2/docker-compose.yml @@ -17,9 +17,12 @@ services: postgres: restart: always image: postgres:latest + environment: + - POSTGRES_PASSWORD=wirepass # Change this password! volumes: - ./postgres-data:/var/lib/postgresql/data + elasticsearch: restart: always image: elasticsearch:2.4 @@ -27,22 +30,25 @@ services: - ./elasticsearch-data:/usr/share/elasticsearch/data command: elasticsearch -Des.index.max_result_window=50000 + memcached: restart: always image: memcached:1 command: memcached -m 2048m + wirecloud: restart: always - image: fiware/wirecloud:dev-composable + image: fiware/wirecloud:1.2 depends_on: - postgres - elasticsearch - memcached environment: - - DEBUG=True - - DEFAULT_THEME=wirecloud.defaulttheme + - DEBUG=False + # - DEFAULT_THEME=wirecloud.defaulttheme - DB_HOST=postgres + - DB_PASSWORD=wirepass # Change this password! - FORWARDED_ALLOW_IPS=* - ELASTICSEARCH2_URL=http://elasticsearch:9200/ - MEMCACHED_LOCATION=memcached:11211 diff --git a/dev-composable/docker-entrypoint.sh b/1.2/docker-entrypoint.sh similarity index 78% rename from dev-composable/docker-entrypoint.sh rename to 1.2/docker-entrypoint.sh index 8320f2f..20880b7 100755 --- a/dev-composable/docker-entrypoint.sh +++ b/1.2/docker-entrypoint.sh @@ -1,18 +1,6 @@ #!/bin/bash -# Wait DB to be accepting requests -exec 8<>/dev/tcp/${DB_HOST}/5432 -DB_STATUS=$? - -i=0 - -while [[ ${DB_STATUS} -ne 0 && ${i} -lt 50 ]]; do - sleep 5 - exec 8<>/dev/tcp/${DB_HOST}/${DB_PORT} - DB_STATUS=$? - - i=${i}+1 -done +set -e # allow the container to be started with `--user` if [ "$(id -u)" = '0' ]; then diff --git a/0.9-composable/manage.py b/1.2/manage.py similarity index 100% rename from 0.9-composable/manage.py rename to 1.2/manage.py diff --git a/1.2/nginx.conf b/1.2/nginx.conf new file mode 100644 index 0000000..4debf13 --- /dev/null +++ b/1.2/nginx.conf @@ -0,0 +1,49 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + server { + + listen 80; + server_name example.org; + client_max_body_size 20M; + charset utf-8; + + location /static { + alias /var/www/static; + } + + location / { + proxy_pass http://wirecloud:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + } +} diff --git a/dev-composable/settings.py b/1.2/settings.py similarity index 88% rename from dev-composable/settings.py rename to 1.2/settings.py index f7b8438..74019e5 100644 --- a/dev-composable/settings.py +++ b/1.2/settings.py @@ -18,17 +18,30 @@ MANAGERS = ADMINS -DATABASES = { - 'default': { - # Only support postgres for now - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': os.environ.get("DB_NAME", "postgres"), - 'USER': os.environ.get("DB_USERNAME", "postgres"), - 'PASSWORD': os.environ.get("DB_PASSWORD", "postgres"), - 'HOST': os.environ.get("DB_HOST", "postgres"), - 'PORT': os.environ.get("DB_PORT", "5432"), +# We only support postgres and sqlite3 for now +if os.environ.get("DB_HOST", "").strip() != "": + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': os.environ.get("DB_NAME", "postgres"), + 'USER': os.environ.get("DB_USERNAME", "postgres"), + 'PASSWORD': os.environ.get("DB_PASSWORD", "postgres"), + 'HOST': os.environ["DB_HOST"], + 'PORT': os.environ.get("DB_PORT", "5432"), + }, + } +else: + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(DATADIR, 'wirecloud.db'), + 'USER': '', + 'PASSWORD': '', + 'HOST': '', + 'PORT': '', + }, } -} + if "ELASTICSEARCH2_URL" in os.environ: HAYSTACK_CONNECTIONS = { @@ -173,7 +186,6 @@ if IDM_AUTH_ENABLED: AUTHENTICATION_BACKENDS = ( 'wirecloud.fiware.social_auth_backend.FIWAREOAuth2', - 'django.contrib.auth.backends.ModelBackend', ) else: AUTHENTICATION_BACKENDS = ( diff --git a/1.2/tests.py b/1.2/tests.py new file mode 100644 index 0000000..aecc1f0 --- /dev/null +++ b/1.2/tests.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. + +import os +import shutil +import time +import unittest +from urllib.parse import parse_qs, urlparse + +import requests +import sh + + +class WireCloudTests(object): + + def test_version_api_should_be_available(self): + response = requests.get("http://localhost/api/version") + self.assertEqual(response.status_code, 200) + + def test_search_engine_should_work(self): + response = requests.get("http://localhost/api/search?namespace=workspace&maxresults=1") + self.assertEqual(response.status_code, 200) + + def test_root_page_should_work(self): + response = requests.get("http://localhost/") + self.assertEqual(response.status_code, 200) + + def test_home_page_should_work(self): + response = requests.get("http://localhost/wirecloud/home") + self.assertEqual(response.status_code, 200) + + def test_should_serve_static_files(self): + response = requests.get("http://localhost/static/theme/wirecloud.defaulttheme/images/logos/header.png") + self.assertEqual(response.status_code, 200) + + +class StandaloneTests(unittest.TestCase, WireCloudTests): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing standalone test case") + print("#\n") + sh.docker_compose("-f", "docker-compose-standalone.yml", "up", d=True, remove_orphans=True, _fg=True) + time.sleep(30) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud-data') + shutil.rmtree('wirecloud-static') + print() + + +class SimpleTests(unittest.TestCase, WireCloudTests): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing simple test case") + print("#\n") + sh.docker_compose("-f", "docker-compose-simple.yml", "up", d=True, remove_orphans=True, _fg=True) + time.sleep(30) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud-data') + shutil.rmtree('wirecloud-static') + print() + + +class ComposedTests(unittest.TestCase, WireCloudTests): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing composed test case") + print("#\n") + sh.docker_compose.up(d=True, remove_orphans=True, _fg=True) + time.sleep(30) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud-data') + shutil.rmtree('wirecloud-static') + shutil.rmtree('elasticsearch-data') + shutil.rmtree('postgres-data') + print() + + +class IDMTests(unittest.TestCase, WireCloudTests): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing idm test case") + print("#\n") + + env = {} + env.update(os.environ) + env["FIWARE_IDM_SERVER"] = "https://accounts.example.com" + env["SOCIAL_AUTH_FIWARE_KEY"] = "wirecloud_test_client_id" + env["SOCIAL_AUTH_FIWARE_SECRET"] = "notused" + sh.docker_compose("-f", "docker-compose-idm.yml", "up", d=True, remove_orphans=True, _env=env, _fg=True) + time.sleep(45) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud-data') + shutil.rmtree('wirecloud-static') + shutil.rmtree('elasticsearch-data') + shutil.rmtree('postgres-data') + print() + + def test_login_should_redirect_to_idm(self): + response = requests.get("http://localhost/login/fiware/", allow_redirects=False) + self.assertEqual(response.status_code, 302) + location = urlparse(response.headers['Location']) + self.assertEqual(location.scheme, 'https') + self.assertEqual(location.netloc, 'accounts.example.com') + self.assertEqual(location.path, '/oauth2/authorize') + parameters = parse_qs(location.query) + self.assertEqual(parameters['client_id'], ['wirecloud_test_client_id']) + self.assertEqual(parameters['redirect_uri'], ['http://localhost/complete/fiware/']) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/dev-composable/urls.py b/1.2/urls.py similarity index 100% rename from dev-composable/urls.py rename to 1.2/urls.py diff --git a/README.md b/README.md index e23d2f4..97bdef7 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,14 @@ # Supported tags and respective `Dockerfile` links # -- [`1.1`, `latest`](https://github.com/Wirecloud/docker-wirecloud/blob/master/1.1/Dockerfile) +- [`1.2`, `latest`](https://github.com/Wirecloud/docker-wirecloud/blob/master/1.2/Dockerfile) +- [`1.1`](https://github.com/Wirecloud/docker-wirecloud/blob/master/1.1/Dockerfile) - [`1.1-composable`, `latest-composable`](https://github.com/Wirecloud/docker-wirecloud/blob/master/1.1-composable/Dockerfile) - [`1.0`](https://github.com/Wirecloud/docker-wirecloud/blob/master/1.0/Dockerfile) - [`1.0-composable`](https://github.com/Wirecloud/docker-wirecloud/blob/master/1.0-composable/Dockerfile) -- [`0.9`](https://github.com/Wirecloud/docker-wirecloud/blob/master/0.9/Dockerfile) -- [`0.9-composable`](https://github.com/Wirecloud/docker-wirecloud/blob/master/0.9-composable/Dockerfile) - [`dev`](https://github.com/Wirecloud/docker-wirecloud/blob/master/dev/Dockerfile) -- [`dev-composable`](https://github.com/Wirecloud/docker-wirecloud/blob/master/dev-composable/Dockerfile) -## What is WireCloud? +# What is WireCloud? WireCloud builds on cutting-edge end-user development, RIA and semantic technologies to offer a next-generation end-user centred web application mashup platform aimed at leveraging the long tail of the Internet of Services. WireCloud builds on cutting-edge end-user (software) development, RIA and semantic technologies to offer a next-generation end-user centred web application mashup platform aimed at allowing end users without programming skills to easily create web applications and dashboards/cockpits (e.g. to visualize their data of interest or to control their domotized home or environment). Web application mashups integrate heterogeneous data, application logic, and UI components (widgets) sourced from the Web to create new coherent and value-adding composite applications. They are targeted at leveraging the "long tail" of the Web of Services (a.k.a. the Programmable Web) by exploiting rapid development, DIY, and shareability. They typically serve a specific situational (i.e. immediate, short-lived, customized) need, frequently with high potential for reuse. Is this "situational" character which precludes them to be offered as 'off-the-shelf' functionality by solution providers, and therefore creates the need for a tool like WireCloud @@ -18,39 +16,214 @@ WireCloud is part of [FIWARE](https://www.fiware.org/). Check it out in the [Cat [![WireCloud's logo](https://raw.githubusercontent.com/Wirecloud/docker-wirecloud/master/logo.png)](https://github.com/Wirecloud/wirecloud) -## How to use these images. -There are two types of images, the "standalone" images and the "composable" images. The standalone images comes with everything ready to run WireCloud directly by running the image and without having to configure it (no recommended for production). The composable images are designed to work with `docker-compose` and support a more flexible configuration scheme. +# How to use this image -## Standalone +``` +$ docker run --name some-wirecloud -p 80:8000 -e DEBUG=True -d fiware/wirecloud +``` -Running the standalone images are really simple: +The following environment variables are also honored for configuring your WireCloud instance: + +- `-e DEBUG=...` (defaults to "False", use "True" for running WireCloud in debug + mode. Debug mode should be enabled for running WireCloud in standalone mode) +- `-e DEFAULT_THEME=...` (defaults to "wirecloud.defaulttheme") +- `-e DB_HOST=...` (defaults to nothing, provide a host value to connect this + image with a DB server) +- `-e DB_NAME=...` (defaults to "postgres") +- `-e DB_USERNAME=...` (defaults to "postgres") +- `-e DB_PASSWORD=...` (defaults to "postgres") +- `-e FORWARDED_ALLOW_IPS=...` (defaults to "*", set this to provide a list of + trusted reverse proxies) +- `-e ELASTICSEARCH2_URL=...` (defaults to nothing, leave it empty to use Whoosh + instead). +- `-e MEMCACHED_LOCATION=...` (defaults to nothing, leave it empty to disable + memcached support) +- `-e FIWARE_IDM_SERVER=...` (defaults to nothing, leave it empty for + authenticating users using the credentials stored on the WireCloud + database.) +- `-e SOCIAL_AUTH_FIWARE_KEY=...` (defaults to nothing) +- `-e SOCIAL_AUTH_FIWARE_SECRET=...` (defaults to nothing) + +When running WireCloud with TLS behind a reverse proxy such as Apache/NGINX +which is responsible for doing TLS termination, be sure to set +the `X-Forwarded-Proto`, `X-Forwarded-Host` and `X-Forwarded-Port` headers +appropriately. + + +## Running manage.py commands + +You can run any available `manage.py` command by using `docker exec -ti some-wirecloud manage.py ...`. For example, you can create superusers/administrators by running the following command: + +``` +$ docker exec -ti some-wirecloud manage.py createsuperuser +Username (leave blank to use 'root'): admin +Email address: ${youremail} +Password: ${yourpassword} +Password (again): ${yourpassword} +Superuser created successfully. +``` + +Regarding commands using the filesystem, take into account that those commands will be executed inside the container and thus the filesystem will be the one used by the container. The `manage.py` script will not check if those commands make changes outside the provided volumes. Anyway, they can be used without any problem. For example, static files can be collected using the following command: ``` -$ docker run --name some-wirecloud -d -p 80:80 fiware/wirecloud:latest +$ docker exec -ti some-wirecloud manage.py collectstatic ``` -This example uses the `latest` version, but it should work also with versions `1.1`, `1.0` and `0.9`. Those images includes `EXPOSE 80` (the http port) so them can be used directly to serve WireCloud. Remember that those images are not meant to be used on production that will require configuring HTTPS. +Use `docker exec -ti some-wirecloud manage.py --help` for getting the list of available commands. -### Customizations -The standalone image uses a volume for `/opt/wirecloud_instance` (the path where the WireCloud instance is stored), this means that any change you make to the `settings.py` file will be persisted. +## ... via `docker stack deploy` or `docker-compose` -If you want to use a different theme, you can create it on `/opt/wirecloud_instance`. See the [documentation](https://wirecloud.readthedocs.io/en/stable/development/platform/themes/) for more info. +Example `docker-compose.yml` for WireCloud: -> **Note**: Rembember that any change made outside the defined volume will be lost if the image is updated. +```yaml +version: "3" -## Composable +services: + + nginx: + restart: always + image: nginx + ports: + - 80:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./wirecloud-static:/var/www/static:ro + depends_on: + - wirecloud + + + postgres: + restart: always + image: postgres + environment: + - POSTGRES_PASSWORD=wirepass # Change this password! + volumes: + - ./postgres-data:/var/lib/postgresql/data + + + elasticsearch: + restart: always + image: elasticsearch:2.4 + volumes: + - ./elasticsearch-data:/usr/share/elasticsearch/data + command: elasticsearch -Des.index.max_result_window=50000 -This image is meant to be used with `docker-compose`. -[Docker compose](https://docs.docker.com/compose/) is a tool that allows you to defining and running multi-container applications with Docker. + memcached: + restart: always + image: memcached:1 + command: memcached -m 2048m + + + wirecloud: + restart: always + image: fiware/wirecloud + depends_on: + - postgres + - elasticsearch + - memcached + environment: + - DEBUG=False + # - DEFAULT_THEME=wirecloud.defaulttheme + - DB_HOST=postgres + - DB_PASSWORD=wirepass # Change this password! + - FORWARDED_ALLOW_IPS=* + - ELASTICSEARCH2_URL=http://elasticsearch:9200/ + - MEMCACHED_LOCATION=memcached:11211 + # Uncomment the following environment variables to enable IDM integration + #- FIWARE_IDM_SERVER=${FIWARE_IDM_SERVER} + #- SOCIAL_AUTH_FIWARE_KEY=${SOCIAL_AUTH_FIWARE_KEY} + #- SOCIAL_AUTH_FIWARE_SECRET=${SOCIAL_AUTH_FIWARE_SECRET} + volumes: + - ./wirecloud-data:/opt/wirecloud_instance/data + - ./wirecloud-static:/var/www/static +``` + +This `docker-compose.yml` file relies on a `nginx.conf` configuration file: + +```nginx +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + -First, install docker compose following [this steps](https://docs.docker.com/compose/install/) +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; -> Take into account that some users have reporeted errors when instaing docker-compose from pip. + access_log /var/log/nginx/access.log main; -You can use [this example `docker-compose.yml` file](https://github.com/Wirecloud/docker-wirecloud/blob/master/hub-docs/docker-compose.yml): + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + server { + + listen 80; + server_name example.org; + client_max_body_size 20M; + charset utf-8; + + location /static { + alias /var/www/static; + } + + location / { + proxy_pass http://wirecloud:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + } +} +``` + +Run `docker stack deploy -c docker-compose.yml wirecloud` (or `docker-compose -f docker-compose.yml up`), wait for it to initialize completely, and visit `http://swarm-ip`, `http://localhost`, or `http://host-ip` (as appropriate). Also, take into account that you should configure https to have a production-ready deployment of WireCloud (not covered by this example). + + +## Customizations + +If you want to customize your WireCloud installation, the best option is to create a new docker image by extending one of the official images and installing new modules. For example, you can follow the following [tutorial](https://wirecloud.readthedocs.io/en/stable/development/platform/themes/) for creating a custom theme and install it on the extended image and use the `DEFAULT_THEME` environment variable to configure it as the default theme. + + +# Using previous versions (WireCloud v1.1 and below) + +WireCloud v1.1 and below uses two images, the "standalone" images and the "composable" images. The standalone images comes with everything ready to run WireCloud directly by running the image and without having to configure it (no recommended for production). The composable images are designed to work with other services running on other containers (e.g. using `docker-compose` or docker swarm) supporting a more flexible configuration scheme. + + +## Standalone + +Running the standalone images are really simple: + +``` +$ docker run --name some-wirecloud -d -p 80:80 fiware/wirecloud:1.1 +``` + +This example uses the `1.1` version, but it should work also with versions `1.0`. Those images includes `EXPOSE 80` (the http port) so them can be used directly to serve WireCloud. In any case, those images are not meant to be used on production that will require, at least, configuring HTTPS. + + +## Composable + +This image is meant to be used running some services (e.g. database) outside the main WireCloud container, that is, deployed manually or deployed using other docker images. + +You can make use of [Docker compose](https://docs.docker.com/compose/) as well as [this example `docker-compose.yml` file](https://github.com/Wirecloud/docker-wirecloud/blob/master/hub-docs/docker-compose.yml) for deploying all the required services: ```yaml version: "3.1" @@ -85,7 +258,7 @@ services: - ./static:/var/www/static ``` -and [this `nginx.conf` file](https://github.com/Wirecloud/docker-wirecloud/blob/master/hub-docs/nginx.conf) as base for deploying your WireCloud infrastructure: +This `docker-compose.yml` file requires configuring nginx, you can use [this `nginx.conf` file](https://github.com/Wirecloud/docker-wirecloud/blob/master/hub-docs/nginx.conf) as base for deploying your WireCloud infrastructure: ```nginx user nginx; @@ -148,63 +321,33 @@ $ docker-compose up -d This docker-compose configuration will detect when the WireCloud configuration is missing and, in that case, it will populate the volume at `/opt/wirecloud_instance` (mapped to the local `wirecloud_instance` folder), the database and the `/var/www/static` volume (mapped to the local `static` folder). This initial configuration will not include any administrator user so, please create one using the `createsuperuser` command. -### Running manage.py commands - -You can run any available `manage.py` command by using `docker-compose exec wirecloud manage.py`. For example, you can create superusers/administrators by running the following command: - -``` -$ docker-compose exec wirecloud manage.py createsuperuser -Username (leave blank to use 'root'): admin -Email address: ${youremail} -Password: ${yourpassword} -Password (again): ${yourpassword} -Superuser created successfully. -``` - -Regarding commands using the filesystem, take into account that those commands will be executed inside the container and thus the filesystem will be the one used by the container. The `manage.py` script will not check if those commands make changes outside the provided volumes. Anyway, they can be used without any problem. For example, static files can be collected using the following command: - -``` -$ docker-compose exec wirecloud manage.py collectstatic -``` - -Use `docker-compose exec wirecloud manage.py --help` for getting the list of available commands. - - -### Customizations - -The composable image uses two volumes, one for `/opt/wirecloud_instance` and another for `/var/www/static`. The only difference with the standalone image is that the static files are stored in `/var/www/static` instead of being stored in `/opt/wirecloud_instance/static`. - -> **Note**: Rembember that any change made outside the defined volumes will be lost if the image is updated. - -Composable images comes preloaded with some python modules to allow enabling extra functionalities. Those modules are: - -- `python-social-auth`: Required to enable IdM configuration. -- `pylibmc`: Required to use memcached. - - -## License +# License View license information for [WireCloud](https://github.com/Wirecloud/wirecloud/blob/develop/LICENSE.txt). -## Supported Docker versions + +# Supported Docker versions This image is officially supported on Docker version 1.7.0. Support for older versions (down to 1.0) is provided on a best-effort basis. -## User Feedback -### Documentation +# User Feedback + +## Documentation This document should provide everything you need to install WireCloud using docker. Anyway, you can find the User & Programmer's Manual and the Administration Guides on [Read the Docs](https://wirecloud.readthedocs.io). -### Issues + +## Issues If you have any problems with or questions about this image, please contact us through a [GitHub issue](https://github.com/Wirecloud/docker-wirecloud/issues). You can also reach many of the official image maintainers via the `fiware` and `fiware-wirecloud` tags on [StackOverflow](http://stackoverflow.com/questions/tagged/fiware-wirecloud). -### Contributing + +## Contributing You are invited to contribute new features, fixes, or updates, large or small; we are always thrilled to receive pull requests, and do our best to process them as fast as we can. diff --git a/dev/.gitignore b/dev/.gitignore new file mode 100644 index 0000000..8c4655e --- /dev/null +++ b/dev/.gitignore @@ -0,0 +1,4 @@ +/elasticsearch-data/ +/postgres-data/ +/wirecloud-instance/ +/wirecloud-static/ diff --git a/dev/Dockerfile b/dev/Dockerfile index 8582b42..e64e67f 100644 --- a/dev/Dockerfile +++ b/dev/Dockerfile @@ -1,36 +1,60 @@ -FROM python:2 +FROM python:3.6-stretch MAINTAINER WireCloud Team -# Install apache2, social-auth and create a wirecloud user -RUN apt-get -y update && \ - apt-get install -y apache2 libapache2-mod-wsgi && \ - pip install --no-cache-dir social-auth-app-django && \ - adduser --system --group --shell /bin/bash wirecloud && \ - rm -rf /var/lib/apt/lists/* - -COPY ["apache-config.conf", "/etc/apache2/sites-enabled/000-default.conf"] - -WORKDIR /opt +ENV DEFAULT_THEME=wirecloud.defaulttheme +ENV FORWARDED_ALLOW_IPS=* +ENV DB_PORT=5432 + +RUN apt-get update && \ + apt-get install -y libmemcached-dev && \ + pip install --no-cache-dir social-auth-app-django "gunicorn==19.3.0" "psycopg2==2.6" pylibmc pysolr "elasticsearch==2.4.1" && \ + rm -rf /var/lib/apt/lists/* && \ + \ + export dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" && \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.10/gosu-$dpkgArch" && \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.10/gosu-$dpkgArch.asc" && \ + export GNUPGHOME="$(mktemp -d)" && \ + for server in $(shuf -e ha.pool.sks-keyservers.net \ + hkp://p80.pool.sks-keyservers.net:80 \ + keyserver.ubuntu.com \ + hkp://keyserver.ubuntu.com:80 \ + pgp.mit.edu) ; do \ + gpg --keyserver "$server" --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && break || : ; \ + done && \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu && \ + rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc && \ + chmod +x /usr/local/bin/gosu && \ + gosu nobody true # Install WireCloud & dependencies RUN git clone --depth=1 https://github.com/Wirecloud/wirecloud.git && \ + pip install "django<=1.11" && \ cd wirecloud/src && \ python setup.py bdist_wheel && \ pip install --no-cache-dir dist/*.whl && \ - cd ../.. \ + cd ../.. && \ rm -rf wirecloud -RUN wirecloud-admin startproject wirecloud_instance --quick-start && \ - chown -R wirecloud:wirecloud wirecloud_instance +COPY ./docker-entrypoint.sh / +COPY ./manage.py /usr/local/bin/ + +RUN adduser --system --group --shell /bin/bash wirecloud && \ + pip install --no-cache-dir channels asgi_ipc asgi_redis asgi_rabbitmq && \ + mkdir -p /opt/wirecloud_instance /var/www/static && \ + cd /opt && \ + wirecloud-admin startproject wirecloud_instance wirecloud_instance && \ + chown -R wirecloud:wirecloud wirecloud_instance /var/www/static && \ + chmod a+x wirecloud_instance/manage.py + +COPY ./settings.py ./urls.py /opt/wirecloud_instance/wirecloud_instance/ WORKDIR /opt/wirecloud_instance -RUN sed -i "s/SECRET_KEY = '[^']\+'/SECRET_KEY = 'TOCHANGE_SECRET_KEY'/g" wirecloud_instance/settings.py -# The volume must be created after running the wirecloud-admin command -VOLUME /opt/wirecloud_instance +# volumes must be created after running the collectstatic command +VOLUME /var/www/static +VOLUME /opt/wirecloud_instance/data -EXPOSE 80 +EXPOSE 8000 -COPY ./docker-entrypoint.sh / ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/dev/apache-config.conf b/dev/apache-config.conf deleted file mode 100644 index 3f1202b..0000000 --- a/dev/apache-config.conf +++ /dev/null @@ -1,41 +0,0 @@ - - - - Require all granted - Order allow,deny - Allow from all - - - - - Options Indexes FollowSymLinks - AllowOverride None - Require all granted - - - ### Wirecloud ### - WSGIPassAuthorization On - - WSGIDaemonProcess wirecloud python-path=/opt/wirecloud_instance user=wirecloud group=wirecloud - WSGIScriptAlias / /opt/wirecloud_instance/wirecloud_instance/wsgi.py - - WSGIProcessGroup wirecloud - - - Alias /static /opt/wirecloud_instance/static - - SetHandler None - - ExpiresActive On - ExpiresDefault "access plus 1 week" - - - Header append Cache-Control "public" - - - - - ExpiresDefault "access plus 3 years" - - - diff --git a/dev/docker-compose-idm.yml b/dev/docker-compose-idm.yml new file mode 100644 index 0000000..58e099a --- /dev/null +++ b/dev/docker-compose-idm.yml @@ -0,0 +1,77 @@ +version: "3" + +services: + + nginx: + restart: always + image: nginx:latest + ports: + - 80:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./wirecloud-static:/var/www/static:ro + depends_on: + - wirecloud + + + postgres: + restart: always + image: postgres:latest + environment: + - POSTGRES_PASSWORD=wirepass # Change this password! + volumes: + - ./postgres-data:/var/lib/postgresql/data + + + elasticsearch: + restart: always + image: elasticsearch:2.4 + volumes: + - ./elasticsearch-data:/usr/share/elasticsearch/data + command: elasticsearch -Des.index.max_result_window=50000 + + + memcached: + restart: always + image: memcached:1 + command: memcached -m 2048m + + + mysql: + restart: always + image: mysql/mysql-server:5.7.21 + environment: + - MYSQL_ROOT_PASSWORD=idm + - MYSQL_ROOT_HOST=% + + + keyrock: + restart: always + image: fiware/idm:7.0.2 + ports: + - 3000:3000 + environment: + - DATABASE_HOST=mysql + + + wirecloud: + restart: always + image: fiware/wirecloud:dev + depends_on: + - postgres + - elasticsearch + - memcached + environment: + - DEBUG=False + # - DEFAULT_THEME=wirecloud.defaulttheme + - DB_HOST=postgres + - DB_PASSWORD=wirepass # Change this password! + - FORWARDED_ALLOW_IPS=* + - ELASTICSEARCH2_URL=http://elasticsearch:9200/ + - MEMCACHED_LOCATION=memcached:11211 + - FIWARE_IDM_SERVER=${FIWARE_IDM_SERVER} + - SOCIAL_AUTH_FIWARE_KEY=${SOCIAL_AUTH_FIWARE_KEY} + - SOCIAL_AUTH_FIWARE_SECRET=${SOCIAL_AUTH_FIWARE_SECRET} + volumes: + - ./wirecloud-data:/opt/wirecloud_instance/data + - ./wirecloud-static:/var/www/static diff --git a/dev/docker-compose-simple.yml b/dev/docker-compose-simple.yml new file mode 100644 index 0000000..e6b4d54 --- /dev/null +++ b/dev/docker-compose-simple.yml @@ -0,0 +1,25 @@ +version: "3" + +services: + + nginx: + restart: always + image: nginx:latest + ports: + - 80:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./wirecloud-static:/var/www/static:ro + depends_on: + - wirecloud + + + wirecloud: + restart: always + image: fiware/wirecloud:dev + environment: + - DEBUG=False + - FORWARDED_ALLOW_IPS=* + volumes: + - ./wirecloud-data:/opt/wirecloud_instance/data + - ./wirecloud-static:/var/www/static diff --git a/dev/docker-compose-standalone.yml b/dev/docker-compose-standalone.yml new file mode 100644 index 0000000..f4a702c --- /dev/null +++ b/dev/docker-compose-standalone.yml @@ -0,0 +1,14 @@ +version: "3" + +services: + + wirecloud: + restart: always + image: fiware/wirecloud:dev + ports: + - 80:8000 + environment: + - DEBUG=True + volumes: + - ./wirecloud-data:/opt/wirecloud_instance/data + - ./wirecloud-static:/var/www/static diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml new file mode 100644 index 0000000..b03ad42 --- /dev/null +++ b/dev/docker-compose.yml @@ -0,0 +1,61 @@ +version: "3" + +services: + + nginx: + restart: always + image: nginx:latest + ports: + - 80:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./wirecloud-static:/var/www/static:ro + depends_on: + - wirecloud + + + postgres: + restart: always + image: postgres:latest + environment: + - POSTGRES_PASSWORD=wirepass # Change this password! + volumes: + - ./postgres-data:/var/lib/postgresql/data + + + elasticsearch: + restart: always + image: elasticsearch:2.4 + volumes: + - ./elasticsearch-data:/usr/share/elasticsearch/data + command: elasticsearch -Des.index.max_result_window=50000 + + + memcached: + restart: always + image: memcached:1 + command: memcached -m 2048m + + + wirecloud: + restart: always + image: fiware/wirecloud:dev + depends_on: + - postgres + - elasticsearch + - memcached + environment: + - DEBUG=False + # - DEFAULT_THEME=wirecloud.defaulttheme + - DB_HOST=postgres + - DB_PASSWORD=wirepass # Change this password! + - FORWARDED_ALLOW_IPS=* + - ELASTICSEARCH2_URL=http://elasticsearch:9200/ + - MEMCACHED_LOCATION=memcached:11211 + # Uncomment the following environment variables to enable IDM integration + #- FIWARE_IDM_SERVER=${FIWARE_IDM_SERVER} + #- SOCIAL_AUTH_FIWARE_KEY=${SOCIAL_AUTH_FIWARE_KEY} + #- SOCIAL_AUTH_FIWARE_SECRET=${SOCIAL_AUTH_FIWARE_SECRET} + volumes: + - ./wirecloud-data:/opt/wirecloud_instance/data + - ./wirecloud-static:/var/www/static diff --git a/dev/docker-entrypoint.sh b/dev/docker-entrypoint.sh index fcdd57b..20880b7 100755 --- a/dev/docker-entrypoint.sh +++ b/dev/docker-entrypoint.sh @@ -1,16 +1,30 @@ #!/bin/bash -sed -i "s/SECRET_KEY = 'TOCHANGE_SECRET_KEY'/SECRET_KEY = '$(python -c "from django.utils.crypto import get_random_string; import re; print(re.escape(get_random_string(50, 'abcdefghijklmnopqrstuvwxyz0123456789%^&*(-_=+)')))")'/g" /opt/wirecloud_instance/wirecloud_instance/settings.py +set -e -# Check if there are any pending migration -python manage.py migrate --fake-initial +# allow the container to be started with `--user` +if [ "$(id -u)" = '0' ]; then + chown -R wirecloud . + chown -R wirecloud /var/www/static +fi -# Collect static files so we take into account custom themes and configurations -python manage.py collectstatic --noinput +# Real entry point +case "$1" in + initdb) + manage.py migrate --fake-initial + manage.py populate + ;; + createdefaultsuperuser) + echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'admin')" | manage.py shell > /dev/null + ;; + createsuperuser) + manage.py createsuperuser + ;; + *) + manage.py collectstatic --noinput + manage.py migrate --fake-initial + manage.py populate -su wirecloud -c "python manage.py populate" - -# Start apache processes in foreground -/usr/sbin/apache2ctl graceful-stop -rm -f /var/run/apache2/apache2.pid -exec /usr/sbin/apache2ctl -D FOREGROUND + gosu wirecloud /usr/local/bin/gunicorn wirecloud_instance.wsgi:application --forwarded-allow-ips "${FORWARDED_ALLOW_IPS}" -w 2 -b :8000 + ;; +esac diff --git a/dev-composable/manage.py b/dev/manage.py similarity index 100% rename from dev-composable/manage.py rename to dev/manage.py diff --git a/dev/nginx.conf b/dev/nginx.conf new file mode 100644 index 0000000..4debf13 --- /dev/null +++ b/dev/nginx.conf @@ -0,0 +1,49 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + server { + + listen 80; + server_name example.org; + client_max_body_size 20M; + charset utf-8; + + location /static { + alias /var/www/static; + } + + location / { + proxy_pass http://wirecloud:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + } +} diff --git a/dev/settings.py b/dev/settings.py new file mode 100644 index 0000000..74019e5 --- /dev/null +++ b/dev/settings.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Django settings for wirecloud_instance project. + +import os +from wirecloud.commons.utils.conf import load_default_wirecloud_conf +from django.core.urlresolvers import reverse_lazy + +DEBUG = os.environ.get("DEBUG", "False").strip().lower() == "true" +BASEDIR = os.path.dirname(os.path.abspath(__file__)) +DATADIR = os.path.join(BASEDIR, "..", "data") +load_default_wirecloud_conf(locals()) + +USE_XSENDFILE = False + +ADMINS = ( + # ('Your Name', 'your_email@example.com'), +) + +MANAGERS = ADMINS + +# We only support postgres and sqlite3 for now +if os.environ.get("DB_HOST", "").strip() != "": + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': os.environ.get("DB_NAME", "postgres"), + 'USER': os.environ.get("DB_USERNAME", "postgres"), + 'PASSWORD': os.environ.get("DB_PASSWORD", "postgres"), + 'HOST': os.environ["DB_HOST"], + 'PORT': os.environ.get("DB_PORT", "5432"), + }, + } +else: + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(DATADIR, 'wirecloud.db'), + 'USER': '', + 'PASSWORD': '', + 'HOST': '', + 'PORT': '', + }, + } + + +if "ELASTICSEARCH2_URL" in os.environ: + HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'wirecloud.commons.haystack_backends.elasticsearch2_backend.Elasticsearch2SearchEngine', + 'URL': os.environ['ELASTICSEARCH2_URL'], + 'INDEX_NAME': 'wirecloud', + }, + } +else: + HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine', + 'PATH': os.path.join(DATADIR, 'index'), + }, + } + +# Hosts/domain names that are valid for this site; required if DEBUG is False +# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts +ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '*').split() + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# In a Windows environment this must be set to your system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale. +USE_L10N = True + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/var/www/example.com/media/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +# Examples: "http://example.com/media/", "http://media.example.com/" +MEDIA_URL = '' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/var/www/example.com/static/" +STATIC_ROOT = "/var/www/static" + +# Controls the absolute file path that linked static will be read from and +# compressed static will be written to when using the default COMPRESS_STORAGE. +COMPRESS_ROOT = STATIC_ROOT + +# URL prefix for static files. +# Example: "http://example.com/static/", "http://static.example.com/" +STATIC_URL = '/static/' + +# Additional locations of static files +# STATICFILES_DIRS = ( +# # Put strings here, like "/home/html/static" or "C:/www/django/static". +# # Always use forward slashes, even on Windows. +# # Don't forget to use absolute paths, not relative paths. +# ) + +# List of finder classes that know how to find static files in +# various locations. +# STATICFILES_FINDERS += ( +# 'django.contrib.staticfiles.finders.FileSystemFinder', +# 'django.contrib.staticfiles.finders.DefaultStorageFinder', +# ) + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '4&0+qo=m4yk!7hohzh&xsw=i&g_7t88*-9_^j(xi!fzm9zz^7l' + +ROOT_URLCONF = 'wirecloud_instance.urls' + +# Python dotted path to the WSGI application used by Django's runserver. +WSGI_APPLICATION = 'wirecloud_instance.wsgi.application' + +# FIWARE IdM configuration +FIWARE_IDM_SERVER = os.environ.get('FIWARE_IDM_SERVER', '').strip() +SOCIAL_AUTH_FIWARE_KEY = os.environ.get('SOCIAL_AUTH_FIWARE_KEY', '').strip() +SOCIAL_AUTH_FIWARE_SECRET = os.environ.get('SOCIAL_AUTH_FIWARE_SECRET', '').strip() +IDM_AUTH_ENABLED = FIWARE_IDM_SERVER and SOCIAL_AUTH_FIWARE_KEY and SOCIAL_AUTH_FIWARE_SECRET + +if IDM_AUTH_ENABLED: + INSTALLED_APPS += ( + 'wirecloud.fiware', + 'social_django', + 'haystack', + ) +else: + INSTALLED_APPS += ( + 'wirecloud.oauth2provider', + 'wirecloud.fiware', + 'haystack', + ) + +# Login/logout URLs +LOGIN_URL = reverse_lazy('login') +LOGOUT_URL = reverse_lazy('wirecloud.root') +LOGIN_REDIRECT_URL = reverse_lazy('wirecloud.root') + +THEME_ACTIVE = os.environ.get("DEFAULT_THEME", "wirecloud.defaulttheme") +DEFAULT_LANGUAGE = 'browser' + +# WGT deployment dirs +CATALOGUE_MEDIA_ROOT = os.path.join(DATADIR, 'catalogue_resources') +GADGETS_DEPLOYMENT_DIR = os.path.join(DATADIR, 'widget_files') + +# Cache settings +CACHES = { + "default": {} +} + +if "MEMCACHED_LOCATION" in os.environ: + CACHES['default'] = { + 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', + 'LOCATION': os.environ['MEMCACHED_LOCATION'], + } +else: + CACHES['default'] = { + 'BACKEND': 'wirecloud.platform.cache.backends.locmem.LocMemCache', + 'OPTIONS': { + 'MAX_ENTRIES': 3000, + }, + } + +NOT_PROXY_FOR = ['localhost', '127.0.0.1'] + +# Allow X-Forwarded-* headers on Django (they are filtered by gunicorn depending on the value of FORWARDED_ALLOW_IPS env var) +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +USE_X_FORWARDED_HOST = True +USE_X_FORWARDED_PORT = True + +# Auth configuration +if IDM_AUTH_ENABLED: + AUTHENTICATION_BACKENDS = ( + 'wirecloud.fiware.social_auth_backend.FIWAREOAuth2', + ) +else: + AUTHENTICATION_BACKENDS = ( + 'django.contrib.auth.backends.ModelBackend', + ) + +DATA_UPLOAD_MAX_MEMORY_SIZE = 262144000 diff --git a/dev/tests.py b/dev/tests.py new file mode 100644 index 0000000..16d49dd --- /dev/null +++ b/dev/tests.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. + +import os +import shutil +import time +import unittest +from urllib.parse import parse_qs, urlparse + +import requests +import sh + + +class WireCloudTests(object): + + def test_version_api_should_be_available(self): + response = requests.get("http://localhost/api/version") + self.assertEqual(response.status_code, 200) + + def test_search_engine_should_work(self): + response = requests.get("http://localhost/api/search?namespace=workspace&maxresults=1") + self.assertEqual(response.status_code, 200) + + def test_root_page_should_work(self): + response = requests.get("http://localhost/") + self.assertEqual(response.status_code, 200) + + def test_home_page_should_work(self): + response = requests.get("http://localhost/wirecloud/home") + self.assertEqual(response.status_code, 200) + + def test_should_serve_static_files(self): + response = requests.get("http://localhost/static/theme/wirecloud.defaulttheme/images/logos/header.png") + self.assertEqual(response.status_code, 200) + + +class StandaloneTests(unittest.TestCase, WireCloudTests): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing standalone test case") + print("#\n") + sh.docker_compose("-f", "docker-compose-standalone.yml", "up", d=True, remove_orphans=True, _fg=True) + time.sleep(40) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud-data') + shutil.rmtree('wirecloud-static') + print() + + +class SimpleTests(unittest.TestCase, WireCloudTests): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing simple test case") + print("#\n") + sh.docker_compose("-f", "docker-compose-simple.yml", "up", d=True, remove_orphans=True, _fg=True) + time.sleep(40) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud-data') + shutil.rmtree('wirecloud-static') + print() + + +class ComposedTests(unittest.TestCase, WireCloudTests): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing composed test case") + print("#\n") + sh.docker_compose.up(d=True, remove_orphans=True, _fg=True) + time.sleep(40) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud-data') + shutil.rmtree('wirecloud-static') + shutil.rmtree('elasticsearch-data') + shutil.rmtree('postgres-data') + print() + + +class IDMTests(unittest.TestCase, WireCloudTests): + + @classmethod + def setUpClass(cls): + print("#") + print("# Initializing idm test case") + print("#\n") + + env = {} + env.update(os.environ) + env["FIWARE_IDM_SERVER"] = "https://accounts.example.com" + env["SOCIAL_AUTH_FIWARE_KEY"] = "wirecloud_test_client_id" + env["SOCIAL_AUTH_FIWARE_SECRET"] = "notused" + sh.docker_compose("-f", "docker-compose-idm.yml", "up", d=True, remove_orphans=True, _env=env, _fg=True) + time.sleep(45) + print() + + @classmethod + def tearDownClass(cls): + print() + print("#") + print("# Removing containers and volumes") + print("#\n") + sh.docker_compose.down(remove_orphans=True, v=True, _fg=True) + shutil.rmtree('wirecloud-data') + shutil.rmtree('wirecloud-static') + shutil.rmtree('elasticsearch-data') + shutil.rmtree('postgres-data') + print() + + def test_login_should_redirect_to_idm(self): + response = requests.get("http://localhost/login/fiware/", allow_redirects=False) + self.assertEqual(response.status_code, 302) + location = urlparse(response.headers['Location']) + self.assertEqual(location.scheme, 'https') + self.assertEqual(location.netloc, 'accounts.example.com') + self.assertEqual(location.path, '/oauth2/authorize') + parameters = parse_qs(location.query) + self.assertEqual(parameters['client_id'], ['wirecloud_test_client_id']) + self.assertEqual(parameters['redirect_uri'], ['http://localhost/complete/fiware/']) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/dev/urls.py b/dev/urls.py new file mode 100644 index 0000000..f3ba079 --- /dev/null +++ b/dev/urls.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- + +from django.conf import settings +from django.conf.urls import include, url +from django.contrib import admin +from django.contrib.auth import views as django_auth +from django.contrib.staticfiles.urls import staticfiles_urlpatterns + +from wirecloud.commons import authentication as wc_auth +from wirecloud.fiware import views as wc_fiware +import wirecloud.platform.urls + +admin.autodiscover() + +urlpatterns = ( + + # Catalogue + url(r'^catalogue/', include('wirecloud.catalogue.urls')), + + # Proxy + url(r'^cdp/', include('wirecloud.proxy.urls')), + + # Login/logout + url(r'^login/?$', wc_fiware.login if settings.IDM_AUTH_ENABLED else django_auth.login, name="login"), + url(r'^logout/?$', wc_auth.logout, name="logout"), + url(r'^admin/logout/?$', wc_auth.logout), + + # Admin interface + url(r'^admin/', include(admin.site.urls)), +) + +if settings.IDM_AUTH_ENABLED: + urlpatterns += (url('', include('social_django.urls', namespace='social')),) + +urlpatterns += wirecloud.platform.urls.urlpatterns +urlpatterns += tuple(staticfiles_urlpatterns()) + +handler400 = "wirecloud.commons.views.bad_request" +handler403 = "wirecloud.commons.views.permission_denied" +handler404 = "wirecloud.commons.views.page_not_found" +handler500 = "wirecloud.commons.views.server_error" diff --git a/latest b/latest index b123147..ea710ab 120000 --- a/latest +++ b/latest @@ -1 +1 @@ -1.1 \ No newline at end of file +1.2 \ No newline at end of file diff --git a/latest-composable b/latest-composable deleted file mode 120000 index 55156b8..0000000 --- a/latest-composable +++ /dev/null @@ -1 +0,0 @@ -1.1-composable \ No newline at end of file