Skip to content

Commit

Permalink
version: 0.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
ztj1993 committed May 13, 2020
1 parent ddb57f7 commit d22007c
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# dockerignore - modifies docker context to exclude files and directories
# https://docs.docker.com/engine/reference/builder/#dockerignore-file

.git
.idea
.gitignore
.dockerignore
venv
__pycache__
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea
venv
*.pyc
19 changes: 19 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM python:3.8-alpine

LABEL maintainer="Ztj <ztj1993@gmail.com>"

ENV MYSQL_HOST="localhost"
ENV MYSQL_PORT="3306"
ENV MYSQL_USER="root"
ENV MYSQL_PASSWORD=""
ENV MYSQL_CHARSET="utf8mb4"

WORKDIR /app

COPY . .

RUN pip install --no-cache-dir -r requirements.txt

ENTRYPOINT [ "python", "main.py" ]

CMD ["--help"]
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# MySQL 工具库

这是一个 MySQL 工具库,由 Python 编写。

今天早晨,在编写 docker-compose 时,多个项目需要共用一个 MySQL 服务器;
希望能找到一个轮子,可惜没有,只能自己造。

## TODO
- [x] 创建用户
- [x] 创建数据库
- [ ] 完成单元测试

## 项目地址
- [GitHub](https://github.com/ztj1993/mysql-tools)
- [DockerHub](https://hub.docker.com/r/ztj1993/mysql-tools)

## 技术栈
- [pymysql](https://pymysql.readthedocs.io/)
- [docopt](https://github.com/docopt/docopt)
- [py-ztj-registry](https://github.com/ztj1993/PythonPackages/tree/master/py_registry)

## 简单使用
```
python main.py --help
python main.py adduser localhost testing
python main.py passwd localhost testing 123456
python main.py --host=localhost create database testing_news
```
37 changes: 37 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: '3'

services:
mysql:
image: mysql:5.7
command: mysqld --default-authentication-plugin=mysql_native_password
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=1
expose:
- 3306
- 33060
ports:
- 3306

phpmyadmin:
image: phpmyadmin/phpmyadmin:4.9
restart: always
environment:
- PMA_HOST=mysql
- PMA_USER=root
expose:
- 80
ports:
- 80
links:
- mysql:mysql

mysql-tools:
build: .
image: mysql-tools
command: adduser % testing
environment:
- MYSQL_HOST=mysql
links:
- mysql:mysql
depends_on:
- mysql
133 changes: 133 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"""
Usage:
mysqltools.py [options] adduser <hostname> <username> [<password>]
mysqltools.py [options] passwd <hostname> <username> [<password>]
mysqltools.py [options] create database <database>
mysqltools.py --help
mysqltools.py --version
Options:
--help show help options.
--version print program version.
--host=host mysql server host [default: localhost]
--port=port mysql server port [default: 3306]
--user=user mysql server user [default: root]
--password=password mysql server password [default: ]
--charset=charset mysql server charset [default: utf8mb4]
Arguments:
hostname mysql host name user
username mysql user name
password mysql user password
database mysql data base
Actions:
adduser add new user
passwd modify user password
"""

__VERSION__ = 'mysqltools 0.0.1'

import os
import logging

import pymysql.cursors
from docopt import docopt
from registry import Registry

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')


class App(object):
def __init__(self, args):
self.args = args
self.options = Registry()
self.init_options()
self.init_env()
self.client = self.mysql_server()

def init_options(self):
self.options.load(dict(args=self.args))
self.options.default('args.<hostname>', 'localhost')
self.options.default('args.<password>', '')

def dispose(self):
args = self.options.get('args')
if args.get('adduser'):
self.adduser()
elif args.get('passwd'):
self.passwd()
elif args.get('create'):
if args.get('database'):
self.create_database()
else:
pass
else:
pass

def mysql_server(self):
options = self.options.get('server')
[logging.debug('MySQL Server: %s=%s' % (key, value)) for key, value in options.items()]
try:
return pymysql.connect(cursorclass=pymysql.cursors.DictCursor, **options)
except pymysql.err.MySQLError as ex:
logging.error(ex)
exit(ex.args[0])

def init_env(self):
"""加载环境变量"""
self.options.set('server', dict(
host=os.getenv('MYSQL_HOST', self.options.get('args.--host')),
port=int(os.getenv('MYSQL_PORT', self.options.get('args.--port'))),
user=os.getenv('MYSQL_USER', self.options.get('args.--user')),
password=os.getenv('MYSQL_PASSWORD', self.options.get('args.--password')),
charset=os.getenv('MYSQL_CHARSET', self.options.get('args.--charset')),
))

def execute(self, sql):
sql_list = [i for i in sql.split('\n') if i != '']
with self.client.cursor() as cursor:
for sql in sql_list:
logging.debug('Execute Sql: %s' % sql)
cursor.execute(sql)
self.client.commit()

def adduser(self):
self.execute(__SQL_ADDUSER__ % dict(
hostname=self.options.get('args.<hostname>'),
username=self.options.get('args.<username>'),
password=self.options.get('args.<password>'),
))

def passwd(self):
self.execute(__SQL_PASSWD__ % dict(
hostname=self.options.get('args.<hostname>'),
username=self.options.get('args.<username>'),
password=self.options.get('args.<password>'),
))

def create_database(self):
self.execute(__SQL_CREATE_DATABASE__ % dict(
database=self.options.get('args.<database>'),
))


__SQL_ADDUSER__ = """
CREATE USER IF NOT EXISTS `%(username)s`@`%(hostname)s` IDENTIFIED BY '%(password)s';
CREATE DATABASE IF NOT EXISTS `%(username)s`;
GRANT ALL PRIVILEGES ON `%(username)s`.* TO `%(username)s`@`%(hostname)s`;
GRANT ALL PRIVILEGES ON `%(username)s\_%%`.* TO `%(username)s`@`%(hostname)s`;
"""

__SQL_PASSWD__ = """
ALTER USER IF EXISTS `%(username)s`@`%(hostname)s` IDENTIFIED BY '%(password)s';
"""

__SQL_CREATE_DATABASE__ = """
CREATE DATABASE IF NOT EXISTS `%(database)s`;
"""

if __name__ == '__main__':
arguments = docopt(__doc__, version=__VERSION__)
[logging.debug('Arguments: %s=%s' % (key, value)) for key, value in arguments.items()]
App(arguments).dispose()
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pymysql==0.9.3
docopt==0.6.2
py-ztj-registry==0.0.2
42 changes: 42 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import unittest

from .main import App


def TestInit():
import os
os.environ['MYSQL_HOST'] = 'localhost'
os.environ['MYSQL_PORT'] = '3306'
os.environ['MYSQL_USER'] = 'root'
os.environ['MYSQL_PASSWORD'] = ''
os.environ['MYSQL_CHARSET'] = 'utf8mb4'


TestInit()


class TestApp(unittest.TestCase):
def test_adduser(self):
"""测试初始化"""
App({
'<hostname>': 'localhost',
'<username>': 'testing',
'<password>': '',
'adduser': True,
}).adduser()

def test_passwd(self):
"""测试初始化"""
App({
'<hostname>': 'localhost',
'<username>': 'testing',
'<password>': '123456',
'adduser': True,
}).passwd()

def test_create_database(self):
App({
'<database>': 'testing',
'create': True,
'database': True,
}).passwd()

0 comments on commit d22007c

Please sign in to comment.