-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.idea | ||
venv | ||
*.pyc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |