From f5cdba78d42b68fd3cf621ec944e3eeac9b19369 Mon Sep 17 00:00:00 2001 From: Thomas MENARD <thomas.menard@pasteur.fr> Date: Mon, 3 Jun 2019 16:16:12 +0200 Subject: [PATCH] First commit --- Dockerfile | 32 +++++++++ Makefile | 39 +++++++++++ README.md | 26 +++++++ __init__.py | 0 manage.py | 24 +++++++ mysite/__init__.py | 0 mysite/settings.py | 115 +++++++++++++++++++++++++++++++ mysite/urls.py | 29 ++++++++ mysite/wsgi.py | 22 ++++++ polls.yaml | 114 ++++++++++++++++++++++++++++++ polls/__init__.py | 0 polls/admin.py | 19 +++++ polls/apps.py | 19 +++++ polls/migrations/0001_initial.py | 45 ++++++++++++ polls/migrations/__init__.py | 0 polls/models.py | 28 ++++++++ polls/tests.py | 13 ++++ polls/urls.py | 21 ++++++ polls/views.py | 19 +++++ requirements.txt | 5 ++ 20 files changed, 570 insertions(+) create mode 100755 Dockerfile create mode 100755 Makefile create mode 100755 __init__.py create mode 100755 manage.py create mode 100755 mysite/__init__.py create mode 100755 mysite/settings.py create mode 100755 mysite/urls.py create mode 100755 mysite/wsgi.py create mode 100755 polls.yaml create mode 100755 polls/__init__.py create mode 100755 polls/admin.py create mode 100755 polls/apps.py create mode 100755 polls/migrations/0001_initial.py create mode 100755 polls/migrations/__init__.py create mode 100755 polls/models.py create mode 100755 polls/tests.py create mode 100755 polls/urls.py create mode 100755 polls/views.py create mode 100755 requirements.txt diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 0000000..ea0d23a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# Copyright 2015, Google, Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START docker] + +# The Google App Engine python runtime is Debian Jessie with Python installed +# and various os-level packages to allow installation of popular Python +# libraries. The source is on github at: +# https://github.com/GoogleCloudPlatform/python-docker +FROM gcr.io/google_appengine/python + +# Create a virtualenv for the application dependencies. +# # If you want to use Python 2, use the -p python2.7 flag. +RUN virtualenv -p python3 /env +ENV PATH /env/bin:$PATH + +ADD requirements.txt /app/requirements.txt +RUN /env/bin/pip install --upgrade pip && /env/bin/pip install -r /app/requirements.txt +ADD . /app + +CMD gunicorn -b :$PORT mysite.wsgi +# [END docker] diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..a06da05 --- /dev/null +++ b/Makefile @@ -0,0 +1,39 @@ +GCLOUD_PROJECT:=$(shell gcloud config list project --format="value(core.project)") + +.PHONY: all +all: deploy + +.PHONY: create-cluster +create-cluster: + gcloud container clusters create polls \ + --scopes "https://www.googleapis.com/auth/userinfo.email","cloud-platform" + +.PHONY: create-bucket +create-bucket: + gsutil mb gs://$(GCLOUD_PROJECT) + gsutil defacl set public-read gs://$(GCLOUD_PROJECT) + +.PHONY: build +build: + docker build -t gcr.io/$(GCLOUD_PROJECT)/polls . + +.PHONY: push +push: build + gcloud docker push -- gcr.io/$(GCLOUD_PROJECT)/polls + +.PHONY: template +template: + sed -i ".tmpl" "s/\$$GCLOUD_PROJECT/$(GCLOUD_PROJECT)/g" polls.yaml + +.PHONY: deploy +deploy: push template + kubectl create -f polls.yaml + +.PHONY: update +update: + kubectl patch deployment polls -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}" + +.PHONY: delete +delete: + kubectl delete rc polls + kubectl delete service polls diff --git a/README.md b/README.md index e69de29..1d45703 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,26 @@ +# Getting started with Django on Google Container Engine + +[![Open in Cloud Shell][shell_img]][shell_link] + +[shell_img]: http://gstatic.com/cloudssh/images/open-btn.png +[shell_link]: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=container_engine/django_tutorial/README.md + +This repository is an example of how to run a [Django](https://www.djangoproject.com/) +app on Google Container Engine. It uses the +[Writing your first Django app](https://docs.djangoproject.com/en/1.11/intro/tutorial01/) +Polls application (parts 1 and 2) as the example app to deploy. From here on +out, we refer to this app as the 'polls' application. + + +# Tutorial +See our [Django on Container Engine](https://cloud.google.com/python/django/container-engine) tutorial for instructions for setting up and deploying this sample application. + + +## Contributing changes + +* See [CONTRIBUTING.md](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/CONTRIBUTING.md) + + +## Licensing + +* See [LICENSE](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/LICENSE) diff --git a/__init__.py b/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..2062ecd --- /dev/null +++ b/manage.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/mysite/__init__.py b/mysite/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/mysite/settings.py b/mysite/settings.py new file mode 100755 index 0000000..bdcb399 --- /dev/null +++ b/mysite/settings.py @@ -0,0 +1,115 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'pf-@jxtojga)z+4s*uwbgjrq$aep62-thd0q7f&o77xtpka!_m' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +# SECURITY WARNING: If you deploy a Django app to production, make sure to set +# an appropriate host here. +# See https://docs.djangoproject.com/en/1.10/ref/settings/ +ALLOWED_HOSTS = ['*'] + +# Application definition + +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'polls' +) + +MIDDLEWARE = ( + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) + +ROOT_URLCONF = 'mysite.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + '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', + ], + }, + }, +] + +WSGI_APPLICATION = 'mysite.wsgi.application' + +# Database +# https://docs.djangoproject.com/en/1.8/ref/settings/#databases + +# [START dbconfig] +DATABASES = { + 'default': { + # If you are using Cloud SQL for MySQL rather than PostgreSQL, set + # 'ENGINE': 'django.db.backends.mysql' instead of the following. + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'polls', + 'USER': os.getenv('DATABASE_USER'), + 'PASSWORD': os.getenv('DATABASE_PASSWORD'), + 'HOST': '127.0.0.1', + 'PORT': '5432', + } +} +# [END dbconfig] + +# Internationalization +# https://docs.djangoproject.com/en/1.8/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.8/howto/static-files/ + +# [START staticurl] +STATIC_URL = '/static/' +# STATIC_URL = 'https://storage.googleapis.com/<your-gcs-bucket>/static/' +# [END staticurl] + +STATIC_ROOT = 'static/' diff --git a/mysite/urls.py b/mysite/urls.py new file mode 100755 index 0000000..bbb417c --- /dev/null +++ b/mysite/urls.py @@ -0,0 +1,29 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf import settings +from django.contrib import admin +from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.urls import include, path + + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('polls.urls')), +] + +# Only serve static files from Django during development +# Use Google Cloud Storage or an alternative CDN for production +if settings.DEBUG: + urlpatterns += staticfiles_urlpatterns() diff --git a/mysite/wsgi.py b/mysite/wsgi.py new file mode 100755 index 0000000..bd3a0d0 --- /dev/null +++ b/mysite/wsgi.py @@ -0,0 +1,22 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") + +application = get_wsgi_application() diff --git a/polls.yaml b/polls.yaml new file mode 100755 index 0000000..6ccc2d3 --- /dev/null +++ b/polls.yaml @@ -0,0 +1,114 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License + +# This file configures the polls application . The frontend serves +# public web traffic. + +# The bookshelf frontend replication controller ensures that at least 3 +# instances of the bookshelf app are running on the cluster. +# For more info about Pods see: +# https://cloud.google.com/container-engine/docs/pods/ +# For more info about Deployments: +# https://kubernetes.io/docs/user-guide/deployments/ + +# [START kubernetes_deployment] +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: polls + labels: + app: polls +spec: + replicas: 3 + template: + metadata: + labels: + app: polls + spec: + containers: + - name: polls-app + # Replace with your project ID or use `make template` + image: gcr.io/<your-project-id>/polls + # This setting makes nodes pull the docker image every time before + # starting the pod. This is useful when debugging, but should be turned + # off in production. + imagePullPolicy: Always + env: + # [START cloudsql_secrets] + - name: DATABASE_USER + valueFrom: + secretKeyRef: + name: cloudsql + key: username + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: cloudsql + key: password + # [END cloudsql_secrets] + ports: + - containerPort: 8080 + + # [START proxy_container] + - image: gcr.io/cloudsql-docker/gce-proxy:1.05 + name: cloudsql-proxy + command: ["/cloud_sql_proxy", "--dir=/cloudsql", + "-instances=<your-cloudsql-connection-string>=tcp:5432", + "-credential_file=/secrets/cloudsql/credentials.json"] + volumeMounts: + - name: cloudsql-oauth-credentials + mountPath: /secrets/cloudsql + readOnly: true + - name: ssl-certs + mountPath: /etc/ssl/certs + - name: cloudsql + mountPath: /cloudsql + # [END proxy_container] + # [START volumes] + volumes: + - name: cloudsql-oauth-credentials + secret: + secretName: cloudsql-oauth-credentials + - name: ssl-certs + hostPath: + path: /etc/ssl/certs + - name: cloudsql + emptyDir: + # [END volumes] +# [END kubernetes_deployment] + +--- + +# [START service] +# The polls service provides a load-balancing proxy over the polls app +# pods. By specifying the type as a 'LoadBalancer', Container Engine will +# create an external HTTP load balancer. +# For more information about Services see: +# https://cloud.google.com/container-engine/docs/services/ +# For more information about external HTTP load balancing see: +# https://cloud.google.com/container-engine/docs/load-balancer +apiVersion: v1 +kind: Service +metadata: + name: polls + labels: + app: polls +spec: + type: LoadBalancer + ports: + - port: 80 + targetPort: 8080 + selector: + app: polls +# [END service] diff --git a/polls/__init__.py b/polls/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/polls/admin.py b/polls/admin.py new file mode 100755 index 0000000..d0fde6f --- /dev/null +++ b/polls/admin.py @@ -0,0 +1,19 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.contrib import admin + +from .models import Question + +admin.site.register(Question) diff --git a/polls/apps.py b/polls/apps.py new file mode 100755 index 0000000..6f98d05 --- /dev/null +++ b/polls/apps.py @@ -0,0 +1,19 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.apps import AppConfig + + +class PollsConfig(AppConfig): + name = 'polls' diff --git a/polls/migrations/0001_initial.py b/polls/migrations/0001_initial.py new file mode 100755 index 0000000..0609ba7 --- /dev/null +++ b/polls/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2015-12-28 23:27 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Choice', + fields=[ + ('id', models.AutoField( + auto_created=True, primary_key=True, serialize=False, + verbose_name='ID')), + ('choice_text', models.CharField(max_length=200)), + ('votes', models.IntegerField(default=0)), + ], + ), + migrations.CreateModel( + name='Question', + fields=[ + ('id', models.AutoField( + auto_created=True, primary_key=True, serialize=False, + verbose_name='ID')), + ('question_text', models.CharField(max_length=200)), + ('pub_date', models.DateTimeField( + verbose_name=b'date published')), + ], + ), + migrations.AddField( + model_name='choice', + name='question', + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to='polls.Question'), + ), + ] diff --git a/polls/migrations/__init__.py b/polls/migrations/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/polls/models.py b/polls/models.py new file mode 100755 index 0000000..c38f6e5 --- /dev/null +++ b/polls/models.py @@ -0,0 +1,28 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.db import models + + +class Question(models.Model): + question_text = models.CharField(max_length=200) + pub_date = models.DateTimeField('date published') + + +class Choice(models.Model): + question = models.ForeignKey(Question, on_delete=models.CASCADE) + choice_text = models.CharField(max_length=200) + votes = models.IntegerField(default=0) + +# Create your models here. diff --git a/polls/tests.py b/polls/tests.py new file mode 100755 index 0000000..d85408e --- /dev/null +++ b/polls/tests.py @@ -0,0 +1,13 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/polls/urls.py b/polls/urls.py new file mode 100755 index 0000000..672ee5c --- /dev/null +++ b/polls/urls.py @@ -0,0 +1,21 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.urls import path + +from . import views + +urlpatterns = [ + path('', views.index, name='index') +] diff --git a/polls/views.py b/polls/views.py new file mode 100755 index 0000000..acc5671 --- /dev/null +++ b/polls/views.py @@ -0,0 +1,19 @@ +# Copyright 2015 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.http import HttpResponse + + +def index(request): + return HttpResponse("Hello, world. You're at the polls index.") diff --git a/requirements.txt b/requirements.txt new file mode 100755 index 0000000..c19a8e2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +Django==2.1.5 +mysqlclient==1.4.1 +wheel==0.32.3 +gunicorn==19.9.0 +psycopg2==2.7.7 -- GitLab