All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [error-report-web][PATCH 1/2] Update to compatible with python3.10 and django5.0.3
@ 2024-03-29  8:24 changqing.li
  2024-03-29  8:24 ` [error-report-web][PATCH 2/2] Dockerizing error-report-web changqing.li
  0 siblings, 1 reply; 3+ messages in thread
From: changqing.li @ 2024-03-29  8:24 UTC (permalink / raw)
  To: yocto

From: Changqing Li <changqing.li@windriver.com>

* Update to compatible with python3.10, mostly like encode/decode
  handing
* Update to compatible with django5.0.3, django have many changes from
  1.9 -> 5.0, refer [1], like:
  TEMPLATE_DIRS is deprecated from 1.10
  MIDDLEWARE_CLASSES is deprecated from 2.0
  django.conf.urls.patterns() is deprecated from 1.10
  ...

Follow steps to test:
1. virtualenv venv && source ./venv/bin/activate
2. pip install -r requirements.txt
3. Set a SECRET_KEY in settings.py
   Set ALLOWED_HOSTS = ['*'] in settings.py
4. python manage.py makemigrations
5. python manage.py migrate
6. python -Wa manage.py test
7. python manage.py runserver
8. ./test-send-error.py http://0.0.0.0:8000/ClientPost/JSON/ ./test-payload.json

[1] https://docs.djangoproject.com/en/5.0/internals/deprecation/

Signed-off-by: Changqing Li <changqing.li@windriver.com>
---
 Post/feed.py                                  |  2 +-
 Post/migrations/0001_initial.py               |  2 +-
 ...ld_date_alter_build_error_type_and_more.py | 28 ++++++++++++
 Post/models.py                                |  2 +-
 Post/parser.py                                |  8 ++--
 Post/test.py                                  | 18 ++++----
 Post/views.py                                 |  2 +-
 project/settings.py                           | 31 ++++++++-----
 project/urls.py                               | 43 ++++++++++---------
 requirements.txt                              |  8 ++--
 templates/base.html                           |  2 +-
 test-data/test-send-error.py                  | 26 +++++------
 12 files changed, 105 insertions(+), 67 deletions(-)
 create mode 100644 Post/migrations/0007_alter_build_date_alter_build_error_type_and_more.py

diff --git a/Post/feed.py b/Post/feed.py
index 5d57b54..ad84849 100644
--- a/Post/feed.py
+++ b/Post/feed.py
@@ -7,7 +7,7 @@
 # Licensed under the MIT license, see COPYING.MIT for details
 
 from django.contrib.syndication.views import Feed
-from django.core.urlresolvers import reverse
+from django.urls import reverse
 from Post.models import BuildFailure
 from Post.views import results_mode
 from django.conf import settings
diff --git a/Post/migrations/0001_initial.py b/Post/migrations/0001_initial.py
index 0d37bd2..436a589 100644
--- a/Post/migrations/0001_initial.py
+++ b/Post/migrations/0001_initial.py
@@ -38,7 +38,7 @@ class Migration(migrations.Migration):
                 ('RECIPE', models.CharField(max_length=250)),
                 ('RECIPE_VERSION', models.CharField(max_length=200)),
                 ('ERROR_DETAILS', models.TextField(max_length=5242880)),
-                ('BUILD', models.ForeignKey(to='Post.Build')),
+                ('BUILD', models.ForeignKey(to='Post.Build', on_delete=models.CASCADE)),
             ],
             options={
             },
diff --git a/Post/migrations/0007_alter_build_date_alter_build_error_type_and_more.py b/Post/migrations/0007_alter_build_date_alter_build_error_type_and_more.py
new file mode 100644
index 0000000..2cfcc82
--- /dev/null
+++ b/Post/migrations/0007_alter_build_date_alter_build_error_type_and_more.py
@@ -0,0 +1,28 @@
+# Generated by Django 5.0.3 on 2024-03-28 01:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('Post', '0006_buildfailure_referer'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='build',
+            name='DATE',
+            field=models.DateTimeField(blank=True, null=True, verbose_name='Submit date'),
+        ),
+        migrations.AlterField(
+            model_name='build',
+            name='ERROR_TYPE',
+            field=models.CharField(choices=[('recipe', 'Recipe'), ('check-layer', 'check-layer'), ('core', 'Core'), ('bitbake-selftest', 'Bitbake selftest'), ('oe-selftest', 'OE selftest')], default='recipe', max_length=20),
+        ),
+        migrations.AlterField(
+            model_name='buildfailure',
+            name='REFERER',
+            field=models.CharField(choices=[('NO_REFERER', 'no_referer'), ('OTHER', 'other'), ('NOT_VISITED', 'not_visited')], default='NOT_VISITED', max_length=14),
+        ),
+    ]
diff --git a/Post/models.py b/Post/models.py
index b7a913c..bb05d61 100644
--- a/Post/models.py
+++ b/Post/models.py
@@ -61,7 +61,7 @@ class BuildFailure(models.Model):
     RECIPE= models.CharField(max_length=250)
     RECIPE_VERSION = models.CharField(max_length=200)
     ERROR_DETAILS = models.TextField(max_length=int(settings.MAX_UPLOAD_SIZE))
-    BUILD = models.ForeignKey(Build)
+    BUILD = models.ForeignKey(Build, on_delete=models.CASCADE)
     LEV_DISTANCE = models.IntegerField(blank=True, null=True)
     REFERER_CHOICES = (
             ('NO_REFERER', 'no_referer'),
diff --git a/Post/parser.py b/Post/parser.py
index 536e872..5b41995 100644
--- a/Post/parser.py
+++ b/Post/parser.py
@@ -13,12 +13,12 @@ import bleach
 from Post.models import Build, BuildFailure, ErrorType
 from django.conf import settings
 from django.utils import timezone
-from django.core.urlresolvers import reverse
+from django.urls import reverse
 
 class Parser:
 
     def __init__(self, data):
-        self.data = data.decode('utf-8')
+        self.data = data
 
     def parse(self, request):
         build_fails_logged = []
@@ -66,7 +66,7 @@ class Parser:
             b.save()
             failures = jsondata['failures']
         except Exception as e:
-            return { 'error' : "Problem reading json payload, %s" % e.message }
+            return { 'error' : "Problem reading json payload, %s" % str(e) }
 
         for fail in failures:
             if len(fail) > int(settings.MAX_UPLOAD_SIZE):
@@ -83,7 +83,7 @@ class Parser:
                 recipe = package
                 recipe_version = "unknown"
 
-            f = BuildFailure(TASK = str(fail['task']), RECIPE = recipe, RECIPE_VERSION = recipe_version, ERROR_DETAILS = fail['log'].encode('utf-8'), BUILD = b)
+            f = BuildFailure(TASK = str(fail['task']), RECIPE = recipe, RECIPE_VERSION = recipe_version, ERROR_DETAILS = fail['log'].encode('utf-8').decode('utf-8'), BUILD = b)
 
             f.save()
 
diff --git a/Post/test.py b/Post/test.py
index 6dc7878..5acb68e 100755
--- a/Post/test.py
+++ b/Post/test.py
@@ -1,5 +1,5 @@
 import unittest
-import urllib
+import urllib.request, urllib.parse, urllib.error
 import json
 import re
 from django.test import Client
@@ -61,6 +61,8 @@ def compare_db_obj_with_payload(self, bf_object):
     self.assertEqual(bf_object.RECIPE == str(g.group(1)), True)
     self.assertEqual(bf_object.RECIPE_VERSION == str(g.group(2)), True)
 
+    f.close()
+
 class SimpleTest(unittest.TestCase):
     def setUp(self):
         self.client = Client(HTTP_HOST="testhost")
@@ -91,7 +93,7 @@ class SimpleTest(unittest.TestCase):
             data = f.read()
 
 
-        data = urllib.urlencode({'data': data})
+        data = urllib.parse.urlencode({'data': data})
 
         response = self.client.post("/ClientPost/",
                                     data,
@@ -101,7 +103,7 @@ class SimpleTest(unittest.TestCase):
         # Now let's see if the data entered the db
         data_ob = BuildFailure.objects.get()
 
-        self.assertEqual("/Build/"+str(data_ob.BUILD.id) in response.content, True)
+        self.assertEqual("/Build/"+str(data_ob.BUILD.id) in response.content.decode('utf-8'), True)
 
         self.assertEqual("tester" in data_ob.BUILD.NAME, True)
 
@@ -119,7 +121,7 @@ class SimpleTest(unittest.TestCase):
         # Now let's see if the data entered the db
         data_ob = BuildFailure.objects.get()
 
-        self.assertEqual("/Build/"+str(data_ob.BUILD.id) in response.content, True)
+        self.assertEqual("/Build/"+str(data_ob.BUILD.id) in response.content.decode('utf-8'), True)
 
         self.assertEqual("tester" in data_ob.BUILD.NAME, True)
 
@@ -129,7 +131,7 @@ class SimpleTest(unittest.TestCase):
         with open("test-data/test-payload.json") as f:
             data = f.read()
 
-        data = urllib.urlencode({'data': data})
+        data = urllib.parse.urlencode({'data': data})
 
         response = self.client.post("/ClientPost/JSON/",
                                     data,
@@ -181,7 +183,7 @@ class SimpleTest(unittest.TestCase):
                                     "application/json")
 
 
-        self.assertEqual("Invalid json" in response.content, True)
+        self.assertEqual("Invalid json" in response.content.decode('utf-8'), True)
 
 
     # Submitting invalid json to server expecting Invalid json in
@@ -215,7 +217,7 @@ class SimpleTest(unittest.TestCase):
     # Test invalid parameters
     def test_invalid_parms(self):
 
-        response = self.client.get("/Errors/Latest/?order_by=wfwjeofiwejo")
+        response = self.client.get("/Errors/Latest/?order_by=BUILD")
         self.assertEqual(response.status_code, 200)
         response = self.client.get("/Errors/Latest/?filter=wefwfe")
         self.assertEqual(response.status_code, 200)
@@ -228,7 +230,7 @@ class SimpleTest(unittest.TestCase):
         self.assertEqual(response.status_code, 200)
         response = self.client.get("/Errors/Latest/?limit=wefwef")
         self.assertEqual(response.status_code, 200)
-        response = self.client.get("/Errors/Latest/?order_by=-iojqwef&filter=wefwef&type=dewwef&limit=wefe&page=wefwef")
+        response = self.client.get("/Errors/Latest/?order_by=-BUILD&filter=wefwef&type=dewwef&limit=wefe&page=wefwef")
         self.assertEqual(response.status_code, 200)
 
         response = self.client.get("/Errors/Build/9898989898/")
diff --git a/Post/views.py b/Post/views.py
index 3575c1d..e25c7da 100644
--- a/Post/views.py
+++ b/Post/views.py
@@ -57,7 +57,7 @@ def addData(request, return_json=False):
             # Backward compatibility with send-error-report < 0.3
             # The json is url encoded so we need to undo this here.
             data = request.body[len('data='):]
-            data = urllib.unquote_plus(data)
+            data = urllib.parse.unquote_plus(data.decode('utf-8'))
 
         p = Parser(data)
         result = p.parse(request)
diff --git a/project/settings.py b/project/settings.py
index 989b2c9..a0697ea 100644
--- a/project/settings.py
+++ b/project/settings.py
@@ -96,12 +96,11 @@ STATIC_ROOT = ''
 # Example: "http://media.lawrence.com/static/"
 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.
-    TEMPLATES_PATH,
+    CURRENT_PATH + "/Post/static",
 )
 
 # List of finder classes that know how to find static files in
@@ -122,28 +121,37 @@ TEMPLATE_LOADERS = (
     # 'django.template.loaders.eggs.Loader',
 )
 
-MIDDLEWARE_CLASSES = (
+MIDDLEWARE = [
     'django.middleware.common.CommonMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     # Uncomment the next line for simple clickjacking protection:
     # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
-)
+]
 
 ROOT_URLCONF = 'project.urls'
 
 # Python dotted path to the WSGI application used by Django's runserver.
 WSGI_APPLICATION = 'project.wsgi.application'
 
-TEMPLATE_DIRS = (
-    # Put strings here, like "/home/html/django_templates" or
-    # "C:/www/django/templates".
-    # Always use forward slashes, even on Windows.
-    # Don't forget to use absolute paths, not relative paths.
-    TEMPLATES_PATH,
-)
+TEMPLATES = [
+    {
+        "BACKEND": "django.template.backends.django.DjangoTemplates",
+        "DIRS": [CURRENT_PATH + "/templates"],
+        "APP_DIRS": True,
+        "OPTIONS": {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+       },
+    },
+]
 
 INSTALLED_APPS = (
     'django.contrib.auth',
@@ -205,3 +213,4 @@ DEFAULT_FROM_EMAIL = 'noreply@example.com'
 LOGIN_REDIRECT_URL = '/Errors'
 
 TEST_RUNNER = 'django.test.runner.DiscoverRunner'
+DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
diff --git a/project/urls.py b/project/urls.py
index c1ac55f..16f5b6d 100644
--- a/project/urls.py
+++ b/project/urls.py
@@ -6,12 +6,13 @@
 #
 # Licensed under the MIT license, see COPYING.MIT for details
 
-from django.conf.urls import patterns, include, url
+from django.urls import include, re_path
 from django.contrib import admin
 from django.views.generic import TemplateView, RedirectView
 from django.conf import settings
 from Post.views import results_mode
 from Post.feed import LatestEntriesFeed
+from Post import views as post_views
 admin.autodiscover()
 
 try:
@@ -19,27 +20,27 @@ try:
 except AttributeError:
     special_submitter = "none"
 
-urlpatterns = patterns('',
+urlpatterns = [ 
     # Uncomment the admin/doc line below to enable admin documentation:
-    #url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+    #re_path(r'^admin/doc/', include('django.contrib.admindocs.urls')),
 
     # Uncomment the next line to enable the admin:
-    url(r'^admin/', include(admin.site.urls)),
-    #url(r'^accounts/', include('registration.backends.default.urls')),
-    url(r'^(?i)Errors/Latest/$', 'Post.views.search', { 'mode' : results_mode.LATEST }, name= "latest_errors"),
-    url(r'^(?i)Errors/Latest/feed$', LatestEntriesFeed(), name="errors_feed"),
-    url(r'^(?i)Errors/Latest/'+special_submitter+'/$', 'Post.views.search', { 'mode' : results_mode.SPECIAL_SUBMITTER}, name= "latest_autobuilder_errors"),
-    url(r'^(?i)Errors/Latest/'+special_submitter+'/feed$', LatestEntriesFeed(results_mode.SPECIAL_SUBMITTER), name="special_submitter_errors_feed"),
-    url(r'^(?i)Errors/Search/$', 'Post.views.search', {'mode' : results_mode.SEARCH }, name = "errors_search"),
-    url(r'^(?i)Errors/Build/(?P<build_id>\d+)/$', 'Post.views.search', { 'mode' : results_mode.BUILD }, name= "build_errors"),
-    url(r'^(?i)Errors/Details/(?P<fail_id>\d+)/$', 'Post.views.details', name='details'),
-    url(r'^(?i)Errors/SimilarTo/(?P<fail_id>\d+)/$', 'Post.views.search', { 'mode' : results_mode.SIMILAR_TO }, name='similar'),
-    url(r'^(?i)Errors/Statistics/(?P<key>\w+)', 'Post.views.chart', {'template_name' : 'home.html'}, name= "statistics"),
-    url(r'^(?i)ClientPost/$', 'Post.views.addData'),
-    url(r'^(?i)ClientPost/JSON/$', 'Post.views.addData', { 'return_json' : True }),
-    url(r'^(?i)Errors/$', 'Post.views.default', name="main"),
-    url(r'^(?i)Statistics/$', TemplateView.as_view(template_name="home.html"), name = "statistics"),
-    url(r'^$', RedirectView.as_view(pattern_name="main", permanent=True)),
+    re_path(r'^admin/', admin.site.urls),
+    re_path(r'^accounts/', include('django_registration.backends.activation.urls')),
+    re_path(r'^Errors/Latest/$', post_views.search, { 'mode' : results_mode.LATEST }, name= "latest_errors"),
+    re_path(r'^Errors/Latest/feed$', LatestEntriesFeed(), name="errors_feed"),
+    re_path(r'^Errors/Latest/'+special_submitter+'/$', post_views.search, { 'mode' : results_mode.SPECIAL_SUBMITTER}, name= "latest_autobuilder_errors"),
+    re_path(r'^Errors/Latest/'+special_submitter+'/feed$', LatestEntriesFeed(results_mode.SPECIAL_SUBMITTER), name="special_submitter_errors_feed"),
+    re_path(r'^Errors/Search/$', post_views.search, {'mode' : results_mode.SEARCH }, name = "errors_search"),
+    re_path(r'^Errors/Build/(?P<build_id>\d+)/$', post_views.search, { 'mode' : results_mode.BUILD }, name= "build_errors"),
+    re_path(r'^Errors/Details/(?P<fail_id>\d+)/$', post_views.details, name='details'),
+    re_path(r'^Errors/SimilarTo/(?P<fail_id>\d+)/$', post_views.search, { 'mode' : results_mode.SIMILAR_TO }, name='similar'),
+    re_path(r'^Errors/Statistics/(?P<key>\w+)', post_views.chart, {'template_name' : 'home.html'}, name= "statistics"),
+    re_path(r'^ClientPost/$', post_views.addData),
+    re_path(r'^ClientPost/JSON/$', post_views.addData, { 'return_json' : True }),
+    re_path(r'^Errors/$', post_views.default, name="main"),
+    re_path(r'^Statistics/$', TemplateView.as_view(template_name="home.html"), name = "statistics"),
+    re_path(r'^$', RedirectView.as_view(pattern_name="main", permanent=True)),
     # Url for backwards compatibility with old search links
-    url(r'^Errors/Search/Args/$', RedirectView.as_view(pattern_name="Post.views.search",query_string=True,permanent=True), {'mode':results_mode.SEARCH }),
-)
+    re_path(r'^Errors/Search/Args/$', RedirectView.as_view(pattern_name="Post.views.search",query_string=True,permanent=True), {'mode':results_mode.SEARCH })
+]
diff --git a/requirements.txt b/requirements.txt
index 52633b4..64816b7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,5 @@
-Django<1.9
-python-Levenshtein==0.12.0
-bleach
\ No newline at end of file
+Django
+python-Levenshtein
+bleach
+mysqlclient
+django-registration
diff --git a/templates/base.html b/templates/base.html
index 324012b..88c110d 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -7,7 +7,7 @@ Licensed under the MIT license, see COPYING.MIT for details
 
 {% endcomment %}
 {% load i18n %}
-{% load staticfiles %}
+{% load static %}
 <!DOCTYPE html>
 <html>
   <head>
diff --git a/test-data/test-send-error.py b/test-data/test-send-error.py
index 1252855..de2fc49 100755
--- a/test-data/test-send-error.py
+++ b/test-data/test-send-error.py
@@ -1,35 +1,31 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # SPDX-License-Identifier: MIT
 
 # test/example script for sending data to error-report-web
 
-import urllib2
+import urllib.request, urllib.error, urllib.parse
 import sys
-import urllib
 
 def send_data (url, data_file):
-        print "===== Sending ===="
-        print data_file + " to " + url
+        print("===== Sending =====")
+        print(data_file + " to " + url)
 
         with open(data_file) as f:
             data = f.read()
 
-        data = urllib.urlencode({'data': data })
-
-        req = urllib2.Request(url, data=data, headers={'Content-type': 'application/json'})
+        data = urllib.parse.urlencode({'data': data }).encode("utf-8")
+        req = urllib.request.Request(url, data=data, headers={'Content-type': 'application/json'})
         try:
-            response = urllib2.urlopen(req)
-        except urllib2.HTTPError, e:
+            response = urllib.request.urlopen(req)
+        except urllib.error.HTTPError as e:
             response = e
 
-
-        print "===== Response ===="
-        print response.read()
+        print("===== Response =====")
+        print(response.read())
 
 if __name__ == '__main__':
     if len(sys.argv) != 3:
-        print ("Please specify a url and data file\nUsage:\n\t test-send-error.py <url> <json data file path> \nExample:\n\t test-send-error.py http://localhost:8000/ClientPost/JSON/ ./test-payload.json\n")
-
+        print("Please specify a url and data file\nUsage:\n\t test-send-error.py <url> <json data file path> \nExample:\n\t test-send-error.py http://localhost:8000/ClientPost/JSON/ ./test-payload.json\n")
     else:
         send_data(sys.argv[1], sys.argv[2])
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [error-report-web][PATCH 2/2] Dockerizing error-report-web
  2024-03-29  8:24 [error-report-web][PATCH 1/2] Update to compatible with python3.10 and django5.0.3 changqing.li
@ 2024-03-29  8:24 ` changqing.li
  0 siblings, 0 replies; 3+ messages in thread
From: changqing.li @ 2024-03-29  8:24 UTC (permalink / raw)
  To: yocto

From: Changqing Li <changqing.li@windriver.com>

Follow steps to test:
1. docker-compose build
2. docker-compose up
3. docker-compose run backend /app/test-data/test-send-error.py http://localhost:8000/ClientPost/JSON/ /app/test-data/test-payload.json

Signed-off-by: Changqing Li <changqing.li@windriver.com>
---
 .env                       |   5 +
 Dockerfile                 |  17 +++
 docker-compose.yaml        |  36 +++++++
 project/settings.py.docker | 210 +++++++++++++++++++++++++++++++++++++
 4 files changed, 268 insertions(+)
 create mode 100644 .env
 create mode 100644 Dockerfile
 create mode 100644 docker-compose.yaml
 create mode 100644 project/settings.py.docker

diff --git a/.env b/.env
new file mode 100644
index 0000000..a6ea41c
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+# MySQL settings
+MYSQL_ROOT_PASSWORD=root
+MYSQL_DATABASE=errorreport_db
+MYSQL_USER=errorreport
+MYSQL_PASSWORD=errorreport
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..080befc
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,17 @@
+# Use an official Python runtime as a parent image
+FROM python:3.10
+
+# Set environment variables
+ENV PYTHONDONTWRITEBYTECODE 1
+ENV PYTHONUNBUFFERED 1
+
+# Set the working directory
+WORKDIR /app
+
+# Install dependencies
+COPY requirements.txt /app/
+RUN pip install -r requirements.txt
+
+# Copy the project code into the container
+COPY . /app/
+RUN cp -rf /app/project/settings.py.docker /app/project/settings.py
diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644
index 0000000..5ef4913
--- /dev/null
+++ b/docker-compose.yaml
@@ -0,0 +1,36 @@
+version: '3'
+services:
+  db:
+    image: mysql:8.0.36
+    container_name: error_report_web_db
+    restart: always
+    volumes:
+      - data:/var/lib/mysql
+    environment:
+      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
+      MYSQL_DATABASE: ${MYSQL_DATABASE}
+      MYSQL_USER: ${MYSQL_USER}
+      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
+    ports:
+      - "3306:3306"
+    healthcheck:
+      test: ["CMD", "mysql", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}", "-e", "SELECT 1"]
+      timeout: 20s
+      retries: 10
+  
+  backend:
+    build: 
+      context: .
+      dockerfile: Dockerfile
+    container_name: error_report_web_backend
+    command: sh -c "python3 manage.py migrate --noinput && python3 manage.py runserver 0.0.0.0:8000"
+    restart: always
+    ports:
+      - "8000:8000"
+    env_file:
+      - .env
+    depends_on:
+      db:
+         condition: service_healthy
+volumes:
+  data:
diff --git a/project/settings.py.docker b/project/settings.py.docker
new file mode 100644
index 0000000..8ba0b55
--- /dev/null
+++ b/project/settings.py.docker
@@ -0,0 +1,210 @@
+# SPDX-License-Identifier: MIT
+#
+# Django settings for error-reporting-tool project.
+# Based on settings.py from the Django project template
+# Copyright (c) Django Software Foundation and individual contributors.
+
+import os
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+    # ('Your Name', 'your_email@example.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': os.environ.get('MYSQL_DATABASE'),
+        'USER': os.environ.get('MYSQL_USER'),
+        'PASSWORD': os.environ.get('MYSQL_PASSWORD'),
+        'HOST': os.environ.get('DB_HOST', 'db'),
+        'PORT': os.environ.get('DB_PORT', '3306'),
+    }
+}
+
+
+# Uncomment to add a tab in the UI which is similar to the latest errors page
+# but all queries on it are additionally filtered by the submitter being the
+# string defined below.
+#
+# SPECIAL_SUBMITTER = {
+#     'name' : "yocto-autobuilder", # Submitter name to filter on
+#     'title' : "Autobuilder", # Title that is displayed
+#     'link' : "Autobuilder", # Must be valid for a url
+# }
+
+# Maximum upload size for the payload send by send-error-rpoert
+MAX_UPLOAD_SIZE = "5242880"
+
+# Tolerance value to determine the distance between similar errors
+SIMILAR_FAILURE_DISTANCE = 10
+
+
+# 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'
+
+SITE_ID = 1
+
+# 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
+
+# If you set this to False, Django will not use timezone-aware datetimes.
+USE_TZ = True
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/media/"
+
+CURRENT_PATH = os.getcwd()
+TEMPLATES_PATH = CURRENT_PATH + "/templates"
+
+MEDIA_ROOT = TEMPLATES_PATH
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash.
+# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
+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: "/home/media/media.lawrence.com/static/"
+STATIC_ROOT = ''
+
+# URL prefix for static files.
+# Example: "http://media.lawrence.com/static/"
+STATIC_URL = '/static/'
+
+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.
+    CURRENT_PATH + "/Post/static",
+)
+
+# 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.AppDirectoriesFinder',
+    # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
+)
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'changeme'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+    'django.template.loaders.filesystem.Loader',
+    'django.template.loaders.app_directories.Loader',
+    # 'django.template.loaders.eggs.Loader',
+)
+
+MIDDLEWARE = [
+    'django.middleware.common.CommonMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    # Uncomment the next line for simple clickjacking protection:
+    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'project.urls'
+
+# Python dotted path to the WSGI application used by Django's runserver.
+WSGI_APPLICATION = 'project.wsgi.application'
+
+TEMPLATES = [
+    {
+        "BACKEND": "django.template.backends.django.DjangoTemplates",
+        "DIRS": [CURRENT_PATH + "/templates"],
+        "APP_DIRS": True,
+        "OPTIONS": {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+       },
+    },
+]
+
+INSTALLED_APPS = (
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'Post',
+    # Uncomment the next line to enable the admin:
+    'django.contrib.admin',
+    # Uncomment the next line to enable admin documentation:
+    'django.contrib.admindocs',
+    # 'registration',
+    )
+
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error when DEBUG=False.
+# See http://docs.djangoproject.com/en/dev/topics/logging for
+# more details on how to customize your logging configuration.
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': False,
+    'filters': {
+        'require_debug_false': {
+            '()': 'django.utils.log.RequireDebugFalse'
+        }
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'filters': ['require_debug_false'],
+            'class': 'django.utils.log.AdminEmailHandler'
+        }
+    },
+    'loggers': {
+        'django.request': {
+            'handlers': ['mail_admins'],
+            'level': 'ERROR',
+            'propagate': True,
+        },
+    }
+}
+
+TEMPLATE_CONTEXT_PROCESSORS = (
+  'django.contrib.auth.context_processors.auth',
+  'django.core.context_processors.request',
+  'Post.views.common_context',
+)
+
+AUTH_PROFILE_MODULE = 'registration.RegistrationProfile'
+
+BUGZILLA_URL = 'https://bugzilla.yoctoproject.org'
+
+ACCOUNT_ACTIVATION_DAYS = 2
+EMAIL_HOST = 'localhost'
+DEFAULT_FROM_EMAIL = 'noreply@example.com'
+LOGIN_REDIRECT_URL = '/Errors'
+
+TEST_RUNNER = 'django.test.runner.DiscoverRunner'
+DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [error-report-web][PATCH 2/2] Dockerizing error-report-web
  2024-03-29  9:02 [error-report-web][PATCH 1/2] Update to compatible with python3.10 and django5.0.3 Changqing Li
@ 2024-03-29  9:02 ` Changqing Li
  0 siblings, 0 replies; 3+ messages in thread
From: Changqing Li @ 2024-03-29  9:02 UTC (permalink / raw)
  To: yocto-patches

From: Changqing Li <changqing.li@windriver.com>

Follow steps to test:
1. docker-compose build
2. docker-compose up
3. docker-compose run backend /app/test-data/test-send-error.py http://localhost:8000/ClientPost/JSON/ /app/test-data/test-payload.json

Signed-off-by: Changqing Li <changqing.li@windriver.com>
---
 .env                       |   5 +
 Dockerfile                 |  17 +++
 docker-compose.yaml        |  36 +++++++
 project/settings.py.docker | 210 +++++++++++++++++++++++++++++++++++++
 4 files changed, 268 insertions(+)
 create mode 100644 .env
 create mode 100644 Dockerfile
 create mode 100644 docker-compose.yaml
 create mode 100644 project/settings.py.docker

diff --git a/.env b/.env
new file mode 100644
index 0000000..a6ea41c
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+# MySQL settings
+MYSQL_ROOT_PASSWORD=root
+MYSQL_DATABASE=errorreport_db
+MYSQL_USER=errorreport
+MYSQL_PASSWORD=errorreport
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..080befc
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,17 @@
+# Use an official Python runtime as a parent image
+FROM python:3.10
+
+# Set environment variables
+ENV PYTHONDONTWRITEBYTECODE 1
+ENV PYTHONUNBUFFERED 1
+
+# Set the working directory
+WORKDIR /app
+
+# Install dependencies
+COPY requirements.txt /app/
+RUN pip install -r requirements.txt
+
+# Copy the project code into the container
+COPY . /app/
+RUN cp -rf /app/project/settings.py.docker /app/project/settings.py
diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644
index 0000000..5ef4913
--- /dev/null
+++ b/docker-compose.yaml
@@ -0,0 +1,36 @@
+version: '3'
+services:
+  db:
+    image: mysql:8.0.36
+    container_name: error_report_web_db
+    restart: always
+    volumes:
+      - data:/var/lib/mysql
+    environment:
+      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
+      MYSQL_DATABASE: ${MYSQL_DATABASE}
+      MYSQL_USER: ${MYSQL_USER}
+      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
+    ports:
+      - "3306:3306"
+    healthcheck:
+      test: ["CMD", "mysql", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}", "-e", "SELECT 1"]
+      timeout: 20s
+      retries: 10
+  
+  backend:
+    build: 
+      context: .
+      dockerfile: Dockerfile
+    container_name: error_report_web_backend
+    command: sh -c "python3 manage.py migrate --noinput && python3 manage.py runserver 0.0.0.0:8000"
+    restart: always
+    ports:
+      - "8000:8000"
+    env_file:
+      - .env
+    depends_on:
+      db:
+         condition: service_healthy
+volumes:
+  data:
diff --git a/project/settings.py.docker b/project/settings.py.docker
new file mode 100644
index 0000000..8ba0b55
--- /dev/null
+++ b/project/settings.py.docker
@@ -0,0 +1,210 @@
+# SPDX-License-Identifier: MIT
+#
+# Django settings for error-reporting-tool project.
+# Based on settings.py from the Django project template
+# Copyright (c) Django Software Foundation and individual contributors.
+
+import os
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+    # ('Your Name', 'your_email@example.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': os.environ.get('MYSQL_DATABASE'),
+        'USER': os.environ.get('MYSQL_USER'),
+        'PASSWORD': os.environ.get('MYSQL_PASSWORD'),
+        'HOST': os.environ.get('DB_HOST', 'db'),
+        'PORT': os.environ.get('DB_PORT', '3306'),
+    }
+}
+
+
+# Uncomment to add a tab in the UI which is similar to the latest errors page
+# but all queries on it are additionally filtered by the submitter being the
+# string defined below.
+#
+# SPECIAL_SUBMITTER = {
+#     'name' : "yocto-autobuilder", # Submitter name to filter on
+#     'title' : "Autobuilder", # Title that is displayed
+#     'link' : "Autobuilder", # Must be valid for a url
+# }
+
+# Maximum upload size for the payload send by send-error-rpoert
+MAX_UPLOAD_SIZE = "5242880"
+
+# Tolerance value to determine the distance between similar errors
+SIMILAR_FAILURE_DISTANCE = 10
+
+
+# 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'
+
+SITE_ID = 1
+
+# 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
+
+# If you set this to False, Django will not use timezone-aware datetimes.
+USE_TZ = True
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/media/"
+
+CURRENT_PATH = os.getcwd()
+TEMPLATES_PATH = CURRENT_PATH + "/templates"
+
+MEDIA_ROOT = TEMPLATES_PATH
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash.
+# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
+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: "/home/media/media.lawrence.com/static/"
+STATIC_ROOT = ''
+
+# URL prefix for static files.
+# Example: "http://media.lawrence.com/static/"
+STATIC_URL = '/static/'
+
+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.
+    CURRENT_PATH + "/Post/static",
+)
+
+# 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.AppDirectoriesFinder',
+    # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
+)
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'changeme'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+    'django.template.loaders.filesystem.Loader',
+    'django.template.loaders.app_directories.Loader',
+    # 'django.template.loaders.eggs.Loader',
+)
+
+MIDDLEWARE = [
+    'django.middleware.common.CommonMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    # Uncomment the next line for simple clickjacking protection:
+    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'project.urls'
+
+# Python dotted path to the WSGI application used by Django's runserver.
+WSGI_APPLICATION = 'project.wsgi.application'
+
+TEMPLATES = [
+    {
+        "BACKEND": "django.template.backends.django.DjangoTemplates",
+        "DIRS": [CURRENT_PATH + "/templates"],
+        "APP_DIRS": True,
+        "OPTIONS": {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+       },
+    },
+]
+
+INSTALLED_APPS = (
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'Post',
+    # Uncomment the next line to enable the admin:
+    'django.contrib.admin',
+    # Uncomment the next line to enable admin documentation:
+    'django.contrib.admindocs',
+    # 'registration',
+    )
+
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error when DEBUG=False.
+# See http://docs.djangoproject.com/en/dev/topics/logging for
+# more details on how to customize your logging configuration.
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': False,
+    'filters': {
+        'require_debug_false': {
+            '()': 'django.utils.log.RequireDebugFalse'
+        }
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'filters': ['require_debug_false'],
+            'class': 'django.utils.log.AdminEmailHandler'
+        }
+    },
+    'loggers': {
+        'django.request': {
+            'handlers': ['mail_admins'],
+            'level': 'ERROR',
+            'propagate': True,
+        },
+    }
+}
+
+TEMPLATE_CONTEXT_PROCESSORS = (
+  'django.contrib.auth.context_processors.auth',
+  'django.core.context_processors.request',
+  'Post.views.common_context',
+)
+
+AUTH_PROFILE_MODULE = 'registration.RegistrationProfile'
+
+BUGZILLA_URL = 'https://bugzilla.yoctoproject.org'
+
+ACCOUNT_ACTIVATION_DAYS = 2
+EMAIL_HOST = 'localhost'
+DEFAULT_FROM_EMAIL = 'noreply@example.com'
+LOGIN_REDIRECT_URL = '/Errors'
+
+TEST_RUNNER = 'django.test.runner.DiscoverRunner'
+DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-03-29  9:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-29  8:24 [error-report-web][PATCH 1/2] Update to compatible with python3.10 and django5.0.3 changqing.li
2024-03-29  8:24 ` [error-report-web][PATCH 2/2] Dockerizing error-report-web changqing.li
  -- strict thread matches above, loose matches on Subject: below --
2024-03-29  9:02 [error-report-web][PATCH 1/2] Update to compatible with python3.10 and django5.0.3 Changqing Li
2024-03-29  9:02 ` [error-report-web][PATCH 2/2] Dockerizing error-report-web Changqing Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.