summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEgor Yurtaev <yurtaev.egor@gmail.com>2015-07-29 16:47:50 +0600
committerEgor Yurtaev <yurtaev.egor@gmail.com>2015-07-29 16:48:30 +0600
commit9c809d2df43229db41bc1fc3d6d35e5a43917a8b (patch)
tree44d9ef655f963de402db9e7e0e45797122a462f8
parentc202d3ca85461fad889e5c05741f3febccb5de6e (diff)
downloadomaha-server-9c809d2df43229db41bc1fc3d6d35e5a43917a8b.zip
omaha-server-9c809d2df43229db41bc1fc3d6d35e5a43917a8b.tar.gz
omaha-server-9c809d2df43229db41bc1fc3d6d35e5a43917a8b.tar.bz2
refactoring: public/private configs
-rw-r--r--.dockerignore2
-rw-r--r--Dockerfile12
-rw-r--r--conf/supervisord.conf12
-rw-r--r--deploy/ebs.config.template28
-rwxr-xr-xdeploy/main.py10
-rw-r--r--deploy/playbook/omaha-server.yml4
-rw-r--r--deploy/playbook/policies/s3_private.json14
-rw-r--r--deploy/playbook/policies/s3_public.json46
-rw-r--r--deploy/playbook/policies/s3_readonly.json13
-rw-r--r--deploy/settings.yml.example28
-rw-r--r--omaha_server/healthcheck/__init__.py0
-rw-r--r--omaha_server/healthcheck/migrations/__init__.py0
-rw-r--r--omaha_server/healthcheck/tests/__init__.py1
-rw-r--r--omaha_server/healthcheck/tests/test_views.py37
-rw-r--r--omaha_server/healthcheck/urls.py27
-rw-r--r--omaha_server/healthcheck/views.py36
-rwxr-xr-xomaha_server/manage.py2
-rw-r--r--omaha_server/omaha/models.py7
-rw-r--r--omaha_server/omaha/tests/test_models.py8
-rw-r--r--omaha_server/omaha/urls.py19
-rw-r--r--omaha_server/omaha_server/s3utils.py19
-rw-r--r--omaha_server/omaha_server/settings.py19
-rw-r--r--omaha_server/omaha_server/settings_prod.py2
-rw-r--r--omaha_server/omaha_server/settings_test.py5
-rw-r--r--omaha_server/omaha_server/urls.py31
-rw-r--r--pavement.py77
26 files changed, 377 insertions, 82 deletions
diff --git a/.dockerignore b/.dockerignore
index 6871028..b8e3656 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,6 +1,8 @@
.git
.dockerignore
+deploy/
+
### Python ###
# Byte-compiled / optimized / DLL files
diff --git a/Dockerfile b/Dockerfile
index 48b5d10..800798b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -30,6 +30,13 @@ RUN cd /usr/src/s3fs-fuse-1.78 && ./autogen.sh && ./configure --prefix=/usr && m
RUN mkdir /srv/omaha_s3
+RUN mkdir $omaha
+WORKDIR ${omaha}
+
+ADD ./requirements.txt $omaha/requirements.txt
+RUN pip install paver --use-mirrors
+RUN pip install -r requirements.txt --use-mirrors
+
ADD . $omaha
# setup all the configfiles
@@ -39,10 +46,5 @@ RUN ln -s /srv/omaha/conf/nginx.conf /etc/nginx/
RUN ln -s /srv/omaha/conf/nginx-app.conf /etc/nginx/sites-enabled/
RUN ln -s /srv/omaha/conf/supervisord.conf /etc/supervisor/conf.d/
-WORKDIR ${omaha}
-
-RUN pip install paver --use-mirrors
-RUN pip install -r requirements.txt --use-mirrors
-
EXPOSE 80
CMD ["paver", "docker_run"]
diff --git a/conf/supervisord.conf b/conf/supervisord.conf
index d7c4d51..bbddf46 100644
--- a/conf/supervisord.conf
+++ b/conf/supervisord.conf
@@ -3,9 +3,13 @@ nodaemon=true
[program:nginx-app]
command = /usr/sbin/nginx
+autostart=true
+autorestart=true
[program:omaha]
command=uwsgi --ini /srv/omaha/conf/uwsgi.ini
+autostart=true
+autorestart=true
[program:celery]
command=celery worker -A omaha_server --loglevel=INFO
@@ -16,4 +20,10 @@ autostart=true
autorestart=true
startsecs=10
stopwaitsecs = 600
-killasgroup=true \ No newline at end of file
+killasgroup=true
+
+
+[program:s3fs]
+command=/usr/bin/s3fs %(ENV_AWS_STORAGE_BUCKET_NAME)s /srv/omaha_s3 -ouse_cache=/tmp -oiam_role=%(ENV_AWS_ROLE)s
+autostart=true
+autorestart=true \ No newline at end of file
diff --git a/deploy/ebs.config.template b/deploy/ebs.config.template
index e7066d8..7deba7d 100644
--- a/deploy/ebs.config.template
+++ b/deploy/ebs.config.template
@@ -28,15 +28,15 @@ app:
all_environments:
solution_stack_name: {{ app.solution_stack_name }}
- #tier_name: 'WebServer'
- #tier_type: 'Standard'
- #tier_version: '1.0'
option_settings:
'aws:autoscaling:launchconfiguration':
InstanceType: {{ app.InstanceType }}
{% set security = ','.join(app.security_groups) -%}
SecurityGroups: {{ security }}
+ {% if app.profile -%}
+ IamInstanceProfile: {{ app.profile }}
+ {% endif -%}
EC2KeyName: {{ app.key_name }}
'aws:autoscaling:asg':
@@ -54,10 +54,6 @@ app:
'aws:elasticbeanstalk:application':
Application Healthcheck URL: {{ app.healthcheck_url }}
- 'aws:elasticbeanstalk:application:environment':
- AWS_ACCESS_KEY_ID: {{ deploy.aws_access_key }}
- AWS_SECRET_KEY: {{ deploy.aws_secret_key }}
-
archive:
files:
- .ebextensions/01_nginx.config:
@@ -82,15 +78,25 @@ app:
- Dockerrun.aws.json
environments:
- {% for env_name in app.environments.keys() -%}
+ {% for env_name in app.environments.keys() %}
{{ env_name }}:
cname_prefix: {{ env_name }}
{% set env = app.environments[env_name] -%}
- {% if env.environment -%}
option_settings:
+ {% if env.environment -%}
'aws:elasticbeanstalk:application:environment':
- {% for key, value in app.environments[env_name].environment.iteritems() -%}
+ HOST_NAME: {{ env_name }}.elasticbeanstalk.com
+ {% for key, value in env.environment.iteritems() -%}
{{ key }}: {{ value }}
{% endfor -%}
{% endif -%}
- {% endfor -%}
+
+ {% if env.option_settings %}
+ {% for key, value in env.option_settings.iteritems() -%}
+ '{{ key }}':
+ {% for k, v in value.iteritems() -%}
+ '{{ k }}': {{ v }}
+ {% endfor -%}
+ {% endfor -%}
+ {% endif -%}
+ {% endfor %}
diff --git a/deploy/main.py b/deploy/main.py
index c2677eb..3ef2a1c 100755
--- a/deploy/main.py
+++ b/deploy/main.py
@@ -34,7 +34,7 @@ DEFAULT_SETTINGS = dict(
solution_stack_name='64bit Amazon Linux 2015.03 v1.4.3 running Docker 1.6.2',
InstanceType='t2.small',
autoscaling=dict(min=1, max=10),
- healthcheck_url='/admin/login/',
+ healthcheck_url='/healthcheck/status/',
),
environment=dict(
DJANGO_SETTINGS_MODULE='omaha_server.settings_dev',
@@ -48,11 +48,15 @@ def get_settings():
with open(SETTINGS_PATH, 'r') as f:
settings = yaml.load(f)
- settings['app'].update(DEFAULT_SETTINGS['app'])
+ app_settings = DEFAULT_SETTINGS['app'].copy()
+ app_settings.update(settings['app'])
+ settings['app'] = app_settings
environments = settings['app']['environments']
for env in environments.keys():
- environments[env]['environment'].update(DEFAULT_SETTINGS['environment'])
+ environment = DEFAULT_SETTINGS['environment'].copy()
+ environment.update(environments[env]['environment'])
+ environments[env]['environment'] = environment
return settings
diff --git a/deploy/playbook/omaha-server.yml b/deploy/playbook/omaha-server.yml
index bee52f2..0ee80dd 100644
--- a/deploy/playbook/omaha-server.yml
+++ b/deploy/playbook/omaha-server.yml
@@ -65,9 +65,9 @@
module: iam_policy
iam_name: omaha-server-s3-readonly
iam_type: role
- policy_name: s3-readonly
+ policy_name: s3-private
state: present
- policy_document: policies/s3_readonly.json
+ policy_document: policies/s3_private.json
- name: create S3 bucket
diff --git a/deploy/playbook/policies/s3_private.json b/deploy/playbook/policies/s3_private.json
new file mode 100644
index 0000000..1863ace
--- /dev/null
+++ b/deploy/playbook/policies/s3_private.json
@@ -0,0 +1,14 @@
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "Stmt1437040026987",
+ "Action": "s3:*",
+ "Effect": "Allow",
+ "Resource": [
+ "arn:aws:s3:::omaha-server",
+ "arn:aws:s3:::omaha-server/*"
+ ]
+ }
+ ]
+}
diff --git a/deploy/playbook/policies/s3_public.json b/deploy/playbook/policies/s3_public.json
new file mode 100644
index 0000000..2c9d1db
--- /dev/null
+++ b/deploy/playbook/policies/s3_public.json
@@ -0,0 +1,46 @@
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Action": [
+ "s3:ListBucket"
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ "arn:aws:s3:::omaha-server-pp"
+ ]
+ }, {
+ "Action": [
+ "s3:GetObject"
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ "arn:aws:s3:::omaha-server-pp/build/*"
+ ]
+ }, {
+ "Action": [
+ "s3:GetObject"
+ ],
+ "Effect": "Allow",
+ "Resource": "arn:aws:s3:::omaha-server-pp/sparkle/*"
+ }, {
+ "Action": [
+ "s3:GetObject",
+ "s3:PutObject"
+ ],
+ "Effect": "Allow",
+ "Resource": "arn:aws:s3:::omaha-server-pp/minidump_archive/*"
+ }, {
+ "Action": [
+ "s3:GetObject",
+ "s3:PutObject"
+ ],
+ "Effect": "Allow",
+ "Resource": "arn:aws:s3:::omaha-server-pp/minidump/*"
+ }, {
+ "Action": [
+ "s3:GetObject"
+ ],
+ "Effect": "Allow",
+ "Resource": "arn:aws:s3:::omaha-server-pp/symbols/*"
+ }]
+}
diff --git a/deploy/playbook/policies/s3_readonly.json b/deploy/playbook/policies/s3_readonly.json
deleted file mode 100644
index 6a725b6..0000000
--- a/deploy/playbook/policies/s3_readonly.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "s3:Get*",
- "s3:List*"
- ],
- "Resource": "*"
- }
- ]
-}
diff --git a/deploy/settings.yml.example b/deploy/settings.yml.example
index e405031..0f9270d 100644
--- a/deploy/settings.yml.example
+++ b/deploy/settings.yml.example
@@ -10,18 +10,40 @@ app:
security_groups:
- omaha-server
- - omaha-server-public
key_name: omaha_server
+ profile: omaha-private
environments:
- omaha-server-dev:
+ omaha-server-private:
environment:
+ OMAHA_SERVER_PRIVATE: true
SECRET_KEY: **********
DB_HOST: postgres.example.com
DB_USER: omaha
DB_NAME: omaha
- DB_PASSWORD: omaha
+ DB_PASSWORD: **********
AWS_STORAGE_BUCKET_NAME: omaha-server
RAVEN_DNS: http://b3615b99118949dbae3c7d06e93fa74c:b8f1c35d08ef4bcaa6810b4d4cdd6fc0@sentry.example.com/2
RAVEN_DSN_STACKTRACE: http://637c17c832f44663b381916d4e0cb34d:9df83034cdfb400f9ce7d47ae4a0cc0b@sentry.example.com/5
REDIS_HOST: redis.example.com
+ DB_PUBLIC_USER: omaha_public
+ DB_PUBLIC_PASSWORD: omaha_public_password
+ AWS_ROLE: omaha-private
+
+ omaha-server-public:
+ option_settings:
+ 'aws:autoscaling:launchconfiguration':
+ IamInstanceProfile: omaha-public
+ environment:
+ OMAHA_SERVER_PRIVATE: false
+ SECRET_KEY: **********
+ DB_HOST: postgres.example.com
+ DB_USER: omaha_public
+ DB_NAME: omaha
+ DB_PASSWORD: omaha_public_password
+ AWS_STORAGE_BUCKET_NAME: omaha-server
+ RAVEN_DNS: http://b3615b99118949dbae3c7d06e93fa74c:b8f1c35d08ef4bcaa6810b4d4cdd6fc0@sentry.example.com/2
+ RAVEN_DSN_STACKTRACE: http://637c17c832f44663b381916d4e0cb34d:9df83034cdfb400f9ce7d47ae4a0cc0b@sentry.example.com/5
+ REDIS_HOST: redis.example.com
+ AWS_ROLE: omaha-public
+ DJANGO_SETTINGS_MODULE: omaha_server.settings_prod
diff --git a/omaha_server/healthcheck/__init__.py b/omaha_server/healthcheck/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omaha_server/healthcheck/__init__.py
diff --git a/omaha_server/healthcheck/migrations/__init__.py b/omaha_server/healthcheck/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omaha_server/healthcheck/migrations/__init__.py
diff --git a/omaha_server/healthcheck/tests/__init__.py b/omaha_server/healthcheck/tests/__init__.py
new file mode 100644
index 0000000..b727357
--- /dev/null
+++ b/omaha_server/healthcheck/tests/__init__.py
@@ -0,0 +1 @@
+# coding: utf8
diff --git a/omaha_server/healthcheck/tests/test_views.py b/omaha_server/healthcheck/tests/test_views.py
new file mode 100644
index 0000000..0443db7
--- /dev/null
+++ b/omaha_server/healthcheck/tests/test_views.py
@@ -0,0 +1,37 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+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 django.core.urlresolvers import reverse
+from django.conf import settings
+
+from rest_framework import status
+from rest_framework.test import APITestCase
+
+
+class StatusTests(APITestCase):
+ def test_view(self):
+ url = reverse('status')
+ data = dict(
+ status='ok',
+ version=settings.APP_VERSION,
+ )
+ response = self.client.get(url)
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.data, data)
diff --git a/omaha_server/healthcheck/urls.py b/omaha_server/healthcheck/urls.py
new file mode 100644
index 0000000..0d826eb
--- /dev/null
+++ b/omaha_server/healthcheck/urls.py
@@ -0,0 +1,27 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+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 django.conf.urls import url
+
+from views import status
+
+urlpatterns = [
+ url(r'^status/$', status, name='status'),
+]
diff --git a/omaha_server/healthcheck/views.py b/omaha_server/healthcheck/views.py
new file mode 100644
index 0000000..5d0f9d1
--- /dev/null
+++ b/omaha_server/healthcheck/views.py
@@ -0,0 +1,36 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+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 django.conf import settings
+
+from rest_framework.decorators import api_view, permission_classes, renderer_classes
+from rest_framework.response import Response
+from rest_framework.permissions import AllowAny
+from rest_framework.renderers import JSONRenderer
+
+
+@api_view(['GET'])
+@permission_classes((AllowAny,))
+@renderer_classes((JSONRenderer,))
+def status(request):
+ return Response(dict(
+ status='ok',
+ version=getattr(settings, 'APP_VERSION')
+ ))
diff --git a/omaha_server/manage.py b/omaha_server/manage.py
index 2ea4a4b..3cbff40 100755
--- a/omaha_server/manage.py
+++ b/omaha_server/manage.py
@@ -4,6 +4,8 @@ import sys
if __name__ == "__main__":
settings = "omaha_server.settings_test" if 'test' in sys.argv else 'omaha_server.settings'
+ if 'test' in sys.argv:
+ os.environ['OMAHA_SERVER_PRIVATE'] = 'True'
os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings)
from django.core.management import execute_from_command_line
diff --git a/omaha_server/omaha/models.py b/omaha_server/omaha/models.py
index 56adc94..2172187 100644
--- a/omaha_server/omaha/models.py
+++ b/omaha_server/omaha/models.py
@@ -38,6 +38,7 @@ from django_extensions.db.fields import (
)
from jsonfield import JSONField
from versionfield import VersionField
+from furl import furl
__all__ = ['Application', 'Channel', 'Platform', 'Version',
@@ -127,11 +128,13 @@ class Version(BaseModel):
@property
def file_package_name(self):
- return os.path.basename(self.file_absolute_url)
+ url = furl(self.file_absolute_url)
+ return os.path.basename(url.pathstr)
@property
def file_url(self):
- return '%s/' % os.path.dirname(self.file_absolute_url)
+ url = furl(self.file_absolute_url)
+ return '%s://%s%s/' % (url.scheme, url.host, os.path.dirname(url.pathstr))
EVENT_DICT_CHOICES = dict(
diff --git a/omaha_server/omaha/tests/test_models.py b/omaha_server/omaha/tests/test_models.py
index ebdb4a6..5d94b48 100644
--- a/omaha_server/omaha/tests/test_models.py
+++ b/omaha_server/omaha/tests/test_models.py
@@ -74,6 +74,14 @@ class VersionModelTest(test.TestCase):
'http://cache.pack.google.com/edgedl/chrome/install/782.112/chrome_installer.exe')
self.assertEqual(version.file_package_name, 'chrome_installer.exe')
self.assertEqual(version.file_url,
+ u'http://cache.pack.google.com/edgedl/chrome/install/782.112/')
+
+ @temporary_media_root(MEDIA_URL='http://cache.pack.google.com/edgedl/chrome/install/782.112/')
+ @patch('omaha.models.version_upload_to', lambda o, f: f)
+ def test_property_s3_meta_data(self):
+ version = VersionFactory.create(file=SimpleUploadedFile('./chrome_installer.exe', ''))
+ self.assertEqual(version.file_package_name, 'chrome_installer.exe')
+ self.assertEqual(version.file_url,
'http://cache.pack.google.com/edgedl/chrome/install/782.112/')
@temporary_media_root()
diff --git a/omaha_server/omaha/urls.py b/omaha_server/omaha/urls.py
index 5f6bb8a..db2d07c 100644
--- a/omaha_server/omaha/urls.py
+++ b/omaha_server/omaha/urls.py
@@ -18,6 +18,7 @@ License for the specific language governing permissions and limitations under
the License.
"""
+from django.conf import settings
from django.conf.urls import url
from omaha.views import UpdateView
@@ -26,11 +27,15 @@ from omaha.views_admin import StatisticsView, StatisticsDetailView, RequestListV
urlpatterns = [
url(r'^service/update2$', UpdateView.as_view(), name='update'),
-
- url(r'^admin/statistics/$', StatisticsView.as_view(), name='omaha_statistics'),
- url(r'^admin/statistics/(?P<name>[a-zA-Z0-9_ ]+)/$', StatisticsDetailView.as_view(),
- name='omaha_statistics_detail'),
- url(r'^admin/statistics/(?P<name>[a-zA-Z0-9_ ]+)/requests/$', RequestListView.as_view(), name='omaha_request_list'),
- url(r'^admin/statistics/requests/(?P<pk>\d+)/$', AppRequestDetailView.as_view(), name='omaha_request_detail'),
- url(r'^admin/set_timezone/$', TimezoneView.as_view(), name='set_timezone'),
]
+
+
+if settings.IS_PRIVATE:
+ urlpatterns += [
+ url(r'^admin/statistics/$', StatisticsView.as_view(), name='omaha_statistics'),
+ url(r'^admin/statistics/(?P<name>[a-zA-Z0-9_ ]+)/$', StatisticsDetailView.as_view(),
+ name='omaha_statistics_detail'),
+ url(r'^admin/statistics/(?P<name>[a-zA-Z0-9_ ]+)/requests/$', RequestListView.as_view(), name='omaha_request_list'),
+ url(r'^admin/statistics/requests/(?P<pk>\d+)/$', AppRequestDetailView.as_view(), name='omaha_request_detail'),
+ url(r'^admin/set_timezone/$', TimezoneView.as_view(), name='set_timezone'),
+ ]
diff --git a/omaha_server/omaha_server/s3utils.py b/omaha_server/omaha_server/s3utils.py
index 639d12c..754ef84 100644
--- a/omaha_server/omaha_server/s3utils.py
+++ b/omaha_server/omaha_server/s3utils.py
@@ -1,6 +1,19 @@
from storages.backends.s3boto import S3BotoStorage
+from furl import furl
-class StaticS3Storage(S3BotoStorage):
+
+class BaseS3Storage(S3BotoStorage):
+ def url(self, name):
+ url = super(BaseS3Storage, self).url(name)
+ if not self.querystring_auth:
+ f = furl(url)
+ if 'x-amz-security-token' in f.args:
+ del f.args['x-amz-security-token']
+ url = f.url
+ return url
+
+
+class StaticS3Storage(BaseS3Storage):
location = 'static'
def url(self, name):
@@ -8,3 +21,7 @@ class StaticS3Storage(S3BotoStorage):
if name.endswith('/') and not url.endswith('/'):
url += '/'
return url
+
+
+class S3Storage(BaseS3Storage):
+ pass
diff --git a/omaha_server/omaha_server/settings.py b/omaha_server/omaha_server/settings.py
index 1bbe9ca..05ea506 100644
--- a/omaha_server/omaha_server/settings.py
+++ b/omaha_server/omaha_server/settings.py
@@ -16,6 +16,8 @@ from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
PROJECT_DIR = BASE_DIR
+IS_PRIVATE = True if os.getenv('OMAHA_SERVER_PRIVATE') == 'True' else False
+
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
@@ -95,19 +97,24 @@ INSTALLED_APPS = (
'feedback',
'sparkle',
'downloads',
+ 'healthcheck',
)
MIDDLEWARE_CLASSES = (
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.common.CommonMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
- 'omaha_server.middlewares.TimezoneMiddleware',
)
+if IS_PRIVATE:
+ MIDDLEWARE_CLASSES = (
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'omaha_server.middlewares.TimezoneMiddleware',
+ ) + MIDDLEWARE_CLASSES
+
ROOT_URLCONF = 'omaha_server.urls'
WSGI_APPLICATION = 'omaha_server.wsgi.application'
diff --git a/omaha_server/omaha_server/settings_prod.py b/omaha_server/omaha_server/settings_prod.py
index 21c6b49..392c879 100644
--- a/omaha_server/omaha_server/settings_prod.py
+++ b/omaha_server/omaha_server/settings_prod.py
@@ -11,7 +11,7 @@ ALLOWED_HOSTS = (os.environ.get('HOST_NAME'), '*')
SECRET_KEY = os.environ.get('SECRET_KEY') or crypto.get_random_string(50)
STATICFILES_STORAGE = 'omaha_server.s3utils.StaticS3Storage'
-DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
+DEFAULT_FILE_STORAGE = 'omaha_server.s3utils.S3Storage'
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
diff --git a/omaha_server/omaha_server/settings_test.py b/omaha_server/omaha_server/settings_test.py
index 372cb62..fe64f53 100644
--- a/omaha_server/omaha_server/settings_test.py
+++ b/omaha_server/omaha_server/settings_test.py
@@ -3,6 +3,9 @@
from .settings import *
+IS_PRIVATE = True
+
+
class DisableMigrations(object):
def __contains__(self, item):
@@ -23,7 +26,7 @@ TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
NOSE_ARGS = [
'--with-coverage',
- '--cover-package=omaha_server,omaha,crash,feedback,sparkle',
+ '--cover-package=omaha_server,omaha,crash,feedback,sparkle,healthcheck',
'--cover-inclusive',
# '--with-doctest',
]
diff --git a/omaha_server/omaha_server/urls.py b/omaha_server/omaha_server/urls.py
index 7dab814..c9b77fc 100644
--- a/omaha_server/omaha_server/urls.py
+++ b/omaha_server/omaha_server/urls.py
@@ -28,22 +28,27 @@ urlpatterns = [
url(r'', include('omaha.urls')),
url(r'', include('crash.urls')),
url(r'', include('feedback.urls')),
- url(r'', include('downloads.urls')),
+ url(r'^healthcheck/', include('healthcheck.urls')),
url(r'^sparkle/', include('sparkle.urls')),
- url(r'^admin/', include(admin.site.urls)),
- url(r'^api/statistics/channels/(?P<app_name>[a-zA-Z0-9_ ]+)/$', omaha.api.StatisticsChannelsView.as_view(),
- name="api-statistics-channels"),
- url(r'^api/statistics/versions/(?P<app_name>[a-zA-Z0-9_ ]+)/$', omaha.api.StatisticsVersionsView.as_view(),
- name="api-statistics-versions"),
- url(r'^api/statistics/months/(?P<app_name>[a-zA-Z0-9_ ]+)/$', omaha.api.StatisticsMonthsDetailView.as_view(),
- name="api-statistics-months-detail"),
- url(r'^api/statistics/months/$', omaha.api.StatisticsMonthsListView.as_view(), name="api-statistics-months-list"),
- url(r'^api/version', omaha.api.ServerVersionView.as_view(), name='api-version'),
- url(r'^api/', include(router.urls)),
- url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
- url(r'^select2/', include('django_select2.urls')),
]
+if settings.IS_PRIVATE:
+ urlpatterns += [
+ url(r'', include('downloads.urls')),
+ url(r'^admin/', include(admin.site.urls)),
+ url(r'^api/statistics/channels/(?P<app_name>[a-zA-Z0-9_ ]+)/$', omaha.api.StatisticsChannelsView.as_view(),
+ name="api-statistics-channels"),
+ url(r'^api/statistics/versions/(?P<app_name>[a-zA-Z0-9_ ]+)/$', omaha.api.StatisticsVersionsView.as_view(),
+ name="api-statistics-versions"),
+ url(r'^api/statistics/months/(?P<app_name>[a-zA-Z0-9_ ]+)/$', omaha.api.StatisticsMonthsDetailView.as_view(),
+ name="api-statistics-months-detail"),
+ url(r'^api/statistics/months/$', omaha.api.StatisticsMonthsListView.as_view(), name="api-statistics-months-list"),
+ url(r'^api/version', omaha.api.ServerVersionView.as_view(), name='api-version'),
+ url(r'^api/', include(router.urls)),
+ url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
+ url(r'^select2/', include('django_select2.urls')),
+ ]
+
if settings.DEBUG:
try:
import debug_toolbar
diff --git a/pavement.py b/pavement.py
index 9d42e6c..b637df3 100644
--- a/pavement.py
+++ b/pavement.py
@@ -20,12 +20,17 @@ the License.
import os
+from raven import Client
from paver.easy import task
from paver.easy import sh
+client = Client(os.environ.get('RAVEN_DNS'))
+
+
@task
def test():
+ os.environ["OMAHA_SERVER_PRIVATE"] = 'True'
sh('./manage.py test --settings=omaha_server.settings_test', cwd='omaha_server')
@@ -70,23 +75,69 @@ def create_admin():
@task
-def mount_s3():
- kwargs = dict(bucket=os.environ['AWS_STORAGE_BUCKET_NAME'],
- mount_point='/srv/omaha_s3')
- env = dict(AWSACCESSKEYID=os.environ['AWS_ACCESS_KEY_ID'],
- AWSSECRETACCESSKEY=os.environ['AWS_SECRET_ACCESS_KEY'])
- cmd = 's3fs {bucket} {mount_point} -ouse_cache=/tmp'.format(**kwargs)
- sh(cmd, env=env)
+def create_db_public_user():
+ import psycopg2
+
+ db_public_user = os.environ['DB_PUBLIC_USER']
+ db_public_password = os.environ['DB_PUBLIC_PASSWORD']
+
+ conn = psycopg2.connect(host=os.environ['DB_HOST'],
+ user=os.environ['DB_USER'],
+ password=os.environ['DB_PASSWORD'],
+ database=os.environ['DB_NAME'])
+ curs = conn.cursor()
+
+ try:
+ # user and group
+ curs.execute("CREATE USER %s WITH PASSWORD '%s';" % (db_public_user, db_public_password))
+ curs.execute('CREATE GROUP public_users WITH USER %s;' % db_public_user)
+
+ # versions
+ curs.execute('GRANT SELECT ON TABLE applications, platforms, platforms_id_seq, '
+ 'channels, channels_id_seq, versions, versions_id_seq, actions, '
+ 'actions_id_seq, omaha_data, omaha_data_id_seq, omaha_partialupdate, '
+ 'omaha_partialupdate_id_seq, sparkle_sparkleversion, '
+ 'sparkle_sparkleversion_id_seq TO GROUP public_users;')
+
+ # crash
+ curs.execute('GRANT SELECT, INSERT, UPDATE ON TABLE crash_crash, crash_crash_id_seq, '
+ 'crash_crashdescription, crash_crashdescription_id_seq TO GROUP public_users;')
+ curs.execute('GRANT SELECT ON TABLE crash_symbols, crash_symbols_id_seq TO GROUP public_users;')
+ curs.execute('GRANT INSERT ON TABLE feedback_feedback, feedback_feedback_id_seq TO GROUP public_users;')
+
+ # statistics
+ curs.execute('GRANT SELECT, INSERT, UPDATE ON TABLE omaha_apprequest, '
+ 'omaha_apprequest_id_seq, omaha_apprequest_events, '
+ 'omaha_apprequest_events_id_seq, omaha_event, omaha_event_id_seq, omaha_hw, '
+ 'omaha_hw_id_seq, omaha_os, omaha_os_id_seq, omaha_request, '
+ 'omaha_request_id_seq TO GROUP public_users;')
+
+ # dev
+ curs.execute('GRANT INSERT ON TABLE httplog_entry, httplog_entry_id_seq TO GROUP public_users;')
+ conn.commit()
+ except psycopg2.ProgrammingError:
+ pass
+ finally:
+ curs.close()
+ conn.close()
@task
def docker_run():
- migrate()
- loaddata()
- create_admin()
- collectstatic()
- # mount_s3()
- sh('/usr/bin/supervisord')
+ try:
+ is_private = True if os.environ.get('OMAHA_SERVER_PRIVATE') == 'True' else False
+
+ if is_private:
+ migrate()
+ create_db_public_user()
+ loaddata()
+ create_admin()
+ collectstatic()
+
+ sh('/usr/bin/supervisord')
+ except:
+ client.captureException()
+ raise
@task