Docker + MYSQL: Can't access mysql outside the container - mysql

I have 2 docker container which both contain mysql database and I open the port 3305, 3306 for each.
for the 3306:3306's container I can access it outside the container by
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, Numeric, String
import os
cwd = os.getcwd()
import sys
sys.path.insert(0, cwd + '/vatic-docker/vatic')
#from models import *
engine = create_engine('mysql://root:1111' '#172.17.0.2:3306/vatic')
Session = sessionmaker (bind = engine)
session = Session()
Base = declarative_base()
However I can't access the 3305:3306 container's mysql database by
engine = create_engine('mysql://root:1111' '#172.17.0.3:3306/vatic')
which return me the error messages:
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (2003, "Can't connect to MySQL server on '172.17.0.3' (111)")
What should I do now?

The port in the connection string is wrong
So
engine = create_engine('mysql://root:1111' '#172.17.0.3:3306/vatic')
should be
engine = create_engine('mysql://root:1111#<host IP>:3305/vatic')
since 3305 is the port that you are exposing on the host machine
Specifically if the Docker host machine has an IP address 192.168.2.100 then the connection should be
engine = create_engine('mysql://root:1111#192.168.2.100:3305/vatic')
format for -p is hostPort:containerPort
https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose

Related

Mocking sqlalchemy.create_engine fails to mock the function

I want to test my DBConnect class, which manages and returns connections made with sqlalchemy.
I want to specifically test that the constructor of DBConnect calls sqlalchemy.create_engine and stores the engine in the connection.
My test function is this:
from unittest import mock
from catcom.db_connect import DBConnect
import os
class MockEngine:
def connect(self):
return "test_connection"
#mock.patch("sqlalchemy.create_engine", return_value=MockEngine())
def test_from_key_uses_correct_key(mock):
print(mock)
db = DBConnect("user", "pw", "127.0.0.1", "1234", "db")
assert db.connection == "test_connection"
However, I see a response of:
E sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) connection to server at "127.0.0.1", port 1234 failed: Connection refused
E Is the server running on that host and accepting TCP/IP connections?
How can I mock the create_engine method without it being actually called?
UPDATE
Adding the DB Connect class and relevant methods.
from sqlalchemy import create_engine
import os
class DBConnect:
"""Manages database connection using SQLalchemy"""
def __init__(self, user: str, password: str, host: str, port: str, database: str):
self.user = user
self.password = password
self.host = host
self.port = port
self.database = database
self.connection = self.connect()
def connect(self):
"""creates a connection object that is used to query database using SQLalchemy core
automatically created in __init__"""
engine = create_engine(
f"postgresql+psycopg2://{self.user}:{self.password}#{self.host}:{self.port}/{self.database}"
)
return engine.connect()
You are importing create_engine out of the sqlalchemy namespace with from sqlalchemy import create_engine, which puts it in the module's namespace.
That's what you need to patch, see where to patch.
#mock.patch('catcom.db_connect.create_engine', return_value='test_success')
Although, patching catcom.db_connect.create_engine to return 'test_success' will cause a problem when the DBConnect.connect method tries to call the connect method of the engine (which will be a string).

Why do I get TCP/IP error when trying to create DB in my Lambda?

So I'm trying to deploy my Django project using lambda, with zappa. I'm using MySQL for DB engine. Now after doing some research, I realized that I needed to create a custom Django command to create DB, since I'm using MySQL. So I created crate_db command, zappa updated, then ran zappa manage dev create_db. Then I got this error: 2004 (HY000): Can't create TCP/IP socket (97)
below is my create_db.py file, for your information.
import sys
import logging
import mysql.connector
import os
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
rds_host = os.environ.get("MY HOST")
db_name = os.environ.get("")
user_name = os.environ.get("MY USERNAME")
password = os.environ.get("MY PASSWORD")
port = os.environ.get("3306")
logger = logging.getLogger()
logger.setLevel(logging.INFO)
class Command(BaseCommand):
help = 'Creates the initial database'
def handle(self, *args, **options):
print('Starting db creation')
try:
db = mysql.connector.connect(host=rds_host, user=user_name,
password=password, db="mysql", connect_timeout=10)
c = db.cursor()
print("connected to db server")
c.execute("""CREATE DATABASE bookcake_db;""")
c.execute("""GRANT ALL ON bookcake_db.* TO 'ryan'#'%'""")
c.close()
print("closed db connection")
except mysql.connector.Error as err:
logger.error("Something went wrong: {}".format(err))
sys.exit()
Any ideas? Thanks.

How to change the authentication configuration of mysql connector to python?

I was trying to connect MySQL with python via the following code.
import mysql.connector
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="qwerty",
auth_plugin="mysql_native_password"
)
print(mydb)
It gave me the following error:-
mysql.connector.errors.NotSupportedError: Authentication plugin 'caching_sha2_password' is not supported
My connector version is:-
C:\Users\samar>pip install mysql-connector-python
Requirement already satisfied: mysql-connector-python in c:\users\samar\anaconda3\lib\site-packages (8.0.21)
import pymysql
host="localhost"
user="root"
passwd="qwerty"
db="<give db name"
def dbConnectivity(host,user, passwd, db):
try:
db = pymysql.connect(host=host,
user=user,
passwd=passwd,
db=db)
cursor = db.cursor()
print("Great !!! Connected to MySQL Db")
return cursor
except pymysql.Error as e:
print("Sorry !! The error in connecting is:" + str(e))
return str(e)
dbConnectivity(host,user,passwd,db)

pymysql.err.InternalError: (1109, "Unknown table 'ALL_PLUGINS' in information_schema")

I have a Python Flask Server setup in an Ubuntu Machine and a MySQL from XAMPP as backend for the same.
How ever when I try to access the database tables from my python program it shows as
pymysql.err.InternalError: (1109, "Unknown table 'ALL_PLUGINS' in information_schema")
but i can access the database directly in MySQL admin page
the sample program I used to access the data.
from flaskext.mysql import MySQL
from flask import (Flask, request, session, g, redirect, url_for, abort, render_template, flash, Response)
import os
from werkzeug.utils import secure_filename
mysql = MySQL()
app = Flask(__name__)
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = 'root'
app.config['MYSQL_DATABASE_DB'] = 'information_schema'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)
#app.route('/')
def insert_student():
qry = "SELECT * FROM ALL_PLUGINS "
conn = mysql.connect()
cursor = conn.cursor()
cursor.execute(qry)
data = cursor.fetchall()
print(data)
conn.commit()
return "Sucess"
if __name__ == '__main__':
app.secret_key = 'super secret key'
app.debug = True
app.run()
instead of normal running I ge the following
the screen shot
Mysql does not have an all_plugins table in information schema. The plugins table (well, view) is called plugins.
So, your query should be:
SELECT * FROM PLUGINS
Based on the comment from #snakecharmerb:
Mariadb, on the other hand, does have all_plugins table, which presumably is the cause of the confusion.

Connecting to MySQL via Python and I have contradictory results

I am trying to connect to a MySQL database hosted on Python Anywhere. In the below example connection.get_server_info() returns a result however connection.is_connected() returns False and I am unsure why.
Here is my code:
import mysql.connector
import sshtunnel
sshtunnel.SSH_TIMEOUT = 5.0
sshtunnel.TUNNEL_TIMEOUT = 5.0
with sshtunnel.SSHTunnelForwarder(
('ssh.pythonanywhere.com'),
ssh_username='USERNAME', ssh_password='PASSWORD',
remote_bind_address=('USERNAME.mysql.pythonanywhere-services.com', 3306)
) as tunnel:
connection = mysql.connector.connect(
user='USERNAME', password='DB_PASSWORD',
host='127.0.0.1', port=tunnel.local_bind_port,
database='USERNAME$default',
)
db_info = connection.get_server_info()
if connection.is_connected():
print('Connected to MySQL DB...version on ', db_info)
else:
print('Failed to connect.')
print(db_info)
connection.close()
I have a paid account on Python Anywhere so SSH tunneling should be possible
It's because you're trying to access the SSH tunnel after it has been closed; the tunnel is closed when you exit the with block, so anything that uses the connection needs to be indented so that it is contained within it. Your code above look like this:
import mysql.connector
import sshtunnel
sshtunnel.SSH_TIMEOUT = 5.0
sshtunnel.TUNNEL_TIMEOUT = 5.0
with sshtunnel.SSHTunnelForwarder(
('ssh.pythonanywhere.com'),
ssh_username='USERNAME', ssh_password='PASSWORD',
remote_bind_address=('USERNAME.mysql.pythonanywhere-services.com', 3306)
) as tunnel:
connection = mysql.connector.connect(
user='USERNAME', password='DB_PASSWORD',
host='127.0.0.1', port=tunnel.local_bind_port,
database='USERNAME$default',
)
db_info = connection.get_server_info()
if connection.is_connected():
print('Connected to MySQL DB...version on ', db_info)
else:
print('Failed to connect.')
print(db_info)
connection.close()