22 Commits

Author SHA1 Message Date
4f736f763e Нет, надо вот так
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is failing
2021-11-01 04:38:54 +03:00
f84994999a Добавил остановку текущих контейнеров
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-01 04:36:41 +03:00
74cd6c6d4b Revert "Добавил простую метрику"
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is passing
Тут этого быть не должно 0_0

This reverts commit 54139d6f76.
2021-11-01 04:30:27 +03:00
49f981708a Добавил шагов
All checks were successful
continuous-integration/drone/push Build is passing
2021-11-01 04:28:02 +03:00
54139d6f76 Добавил простую метрику
All checks were successful
continuous-integration/drone/push Build is passing
2021-10-31 02:24:54 +03:00
4ab80616a6 Добавил название проекта
All checks were successful
continuous-integration/drone/push Build is passing
2021-10-19 10:32:58 +00:00
04905c59db Merge pull request 'Настроил сборку в drone' (#2) from drone into master
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone Build is passing
Reviewed-on: http://git.lulzette.ru/lulzette/pycms/pulls/2
2021-10-19 05:29:56 +03:00
c4602b9d4e change runner
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-10-19 02:26:08 +00:00
2f5867028e fix
Some checks reported errors
continuous-integration/drone/push Build is failing
continuous-integration/drone Build was killed
2021-10-19 02:16:18 +00:00
1aa4be2e47 Drone
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2021-10-19 02:14:31 +00:00
3aa77129ec Кое-какие тесты 2021-10-19 00:53:17 +00:00
32a2678170 Запихнул в docker-compose 2021-10-18 15:16:02 +00:00
6cd33f25be requirements 2021-10-18 13:51:01 +00:00
7c7db5bca0 Добавил timestamp создания записи 2021-09-27 02:25:02 +03:00
755e7c5ce4 Проверка на существование БД/коллекции 2021-09-27 02:19:19 +03:00
85a860eb1a TODO's 2021-09-20 02:18:03 +03:00
5aecf2d643 Some fixes 2021-09-18 04:48:04 +03:00
f72c941a3a Сделал создание конфига при его отсутствии 2021-09-17 15:57:50 +03:00
539d53d209 Добавил чтение конфига 2021-09-17 15:50:18 +03:00
28b98a9127 Добавил класс с конфигом, поправил вызов классов 2021-09-17 15:29:50 +03:00
ee18b5535c Привет, классы 2021-09-17 14:29:32 +03:00
bb64fbaf62 Написал маршруты и TODO 2021-09-10 09:22:01 +03:00
8 changed files with 201 additions and 47 deletions

22
.drone.yml Normal file
View File

@@ -0,0 +1,22 @@
kind: pipeline
type: exec
name: build
steps:
- name: build
commands:
- docker-compose -p pycms build
- name: test
commands:
- docker-compose -p pycms up --build --abort-on-container-exit
- name: push
commands:
- docker-compose -p pycms push
- name: run
commands:
- docker-compose -p pycms down
- docker-compose -p pycms up -d

9
Dockerfile Normal file
View File

@@ -0,0 +1,9 @@
FROM python:latest
ADD . /app
WORKDIR /app
RUN pip3 install --upgrade pip && pip3 install -r requirements.txt
EXPOSE 8080
CMD python3 main.py

View File

@@ -20,3 +20,19 @@ Index page:
} }
``` ```
# Routes:
GET /post — список статей.
GET /post/name — отдельная статья.
POST /admin/posts — создать статью.
PUT /admin/posts — обновить статью.
DELETE /admin/posts/:id — удалить статью.
Все маршруты, которые начинаются с «/admin» требуют аутентификацию пользователя. Для stateless-сервиса очень удобно использовать Basic-аутентификацию, т.к. каждый запрос содержит логин и пароль пользователя.
# TODO:
* Переписать маршруты под админку
* Добавить авторизацию
* Добавить конфигурацию

5
config.ini Normal file
View File

@@ -0,0 +1,5 @@
[DB]
host = db
port = 27017
name = pycms

18
docker-compose.yml Normal file
View File

@@ -0,0 +1,18 @@
version: '3'
services:
server:
build: .
ports:
- 8080:8080
volumes:
- ./config.ini:/app/config.ini
depends_on:
- db
db:
image: mongo
tests:
build: .
command: bash ./test.sh
depends_on:
- db
- server

162
main.py
View File

@@ -1,10 +1,107 @@
#!/usr/bin/python3 #!/usr/bin/python3
from bottle import abort, route, run, template, debug, request from bottle import abort, route, run, request
import pymongo import pymongo
import time
# TODO: auth to /admin
# TODO: timestamps to posts
# TODO: author to posts and multiple users
# TODO: add bottle's params to config
mongoclient = pymongo.MongoClient('localhost', 27017)
database = mongoclient['pycms'] class Config:
"""
posts - table with posts
config structure:
DB:
- host
- port
- dbname
"""
def __init__(self):
"""
Init config
"""
self.readConfig()
mongoclient = pymongo.MongoClient(self.host, self.port)
if self.dbname not in mongoclient.list_database_names():
print('DB not found, creating')
database = mongoclient[self.dbname]
# TODO: Create table if not exists
if 'posts' not in database.list_collection_names():
print('Table not fount, creating')
posts = database['posts'] posts = database['posts']
self.posts = posts
def readConfig(self):
"""
Read config file, if not exists - call self.createConfig()
"""
import configparser
config = configparser.ConfigParser()
if not config.read('config.ini'):
self.createConfig(config)
db = config['DB']
self.host = db['host']
self.port = int(db['port'])
self.dbname = db['name']
def createConfig(self, config):
"""
Create config file
"""
config['DB'] = {}
db = config['DB']
db['host'] = 'localhost'
db['port'] = '27017'
db['name'] = 'pycms'
with open('config.ini', 'w') as cfgfile:
config.write(cfgfile)
class Back():
"""
All actions that will be triggered by http
"""
def getRootPost(self):
try:
return posts.find_one({'name': '_root_'})['text']
except TypeError:
return abort(404, 'No such page')
def getPost(self, name):
try:
return posts.find_one({'name': name})['text']
except TypeError:
return abort(404, 'No such page')
def getAllPosts(self):
# TODO: clear up output, remove '_id' and 'body',
# now there should be only
dict_posts = list()
for i in posts.find():
dict_posts.append(i)
return str(dict_posts)
def updatePost(self, name, body):
# TODO: return RESTful error/success result
# If post exists, update it
if posts.find_one({'name': name}):
newPost = {'$set': {'text': body}}
return str(posts.update_one({'name': name}, newPost))
# Else - create new
else:
newPost = {'name': name, 'text': body,
'create_timestamp': str(time.time())}
return str(posts.insert_one(newPost).inserted_id)
def deletePost(self, name):
# TODO: return RESTful error/success result
return bool(posts.delete_one({'name': name}).deleted_count)
@route('/post/<name>') @route('/post/<name>')
@@ -12,68 +109,43 @@ def post(name):
''' '''
Get post Get post
''' '''
try: return str(back.getPost(name))
return posts.find_one({'name':name})['text']
except TypeError:
return abort(404, 'No such page')
@route('/post/<name>', method='POST') @route('/admin/post/<name>', method='POST')
def post(name): def postUpd(name):
''' '''
Insert/Update post Insert/Update post
''' '''
body = request.forms.get('body') body = request.forms.get('body')
# If post exists, update it return back.updatePost(name=name, body=body)
if posts.find_one({'name': name}):
newPost = {'$set': {'text': body}}
return str(posts.update_one({'name': name}, newPost))
# Else - create new
else:
newPost = {'name': name, 'text': body}
return str(posts.insert_one(newPost).inserted_id)
@route('/post/<name>', method='DELETE') @route('/admin/post/<name>', method='DELETE')
def post(name): def postDel(name):
''' '''
Delete post by name Delete post by name
''' '''
return str(posts.delete_one({'name':name})) return str(back.deletePost(name))
@route('/posts')
@route('/post')
def all_posts(): def all_posts():
''' '''
Returns all posts Returns all posts
''' '''
dict_posts = list() return back.getAllPosts()
for i in posts.find():
dict_posts.append(i)
return str(dict_posts)
@route('/') @route('/')
def index(): def index():
try: return back.getRootPost()
return posts.find_one({'name':'/'})['text']
except TypeError:
return abort(404, 'No such page')
@route('/', method='POST')
def post():
'''
Insert/Update post
'''
body = request.forms.get('body')
# If post exists, update it
if posts.find_one({'name': '/'}):
newPost = {'$set': {'text': body}}
return str(posts.update_one({'name': '/'}, newPost))
# Else - create new
else:
newPost = {'name': '/', 'text': body}
return str(posts.insert_one(newPost).inserted_id)
if __name__ == '__main__': if __name__ == '__main__':
run(host='0.0.0.0', port=8081, reloader=True, debug=True) print("Init")
cfg = Config()
print("Configured")
back = Back()
posts = cfg.posts
run(host='0.0.0.0', port=8080, reloader=True, debug=True)

2
requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
bottle==0.12.19
pymongo==3.12.0

10
test.sh Normal file
View File

@@ -0,0 +1,10 @@
#!/bin/bash
curl_cmd='curl -s -w "%{http_code}" -o /dev/null'
url='server:8080'
$curl_cmd -X POST $url/admin/post/test -F 'body=testpage' && echo ": Create success" || echo ': create fail'
$curl_cmd $url/post/test && echo ": get Success" || echo ': get fail'
$curl_cmd -X POST $url/admin/post/test -F 'body=testpage2' && echo ": Update success" || echo ': update fail'
$curl_cmd -X DELETE $url/admin/post/test && echo ": delete success" || echo ': delete fail'