connecting to and using the same database in MongoDB python - python

I tried to connect to MongoDb server remotely using python pymongo, but when I tried to display documents from collection I got error message as
"pymongo.errors.OperationFailure: not authorized on pt to execute command { find: "devices", filter: {} }" .
Also when I tried get single record from mongo, it will not display the record details instead it will display as
"pymongo.cursor.Cursor object at 0x000001E883A14F98".
Mongo Server Details: Host: Someth-pt-ved-01
user: uname
pwd: mypass
authenticationDatabase: pt
collection: devices
My python code for connection is:
from pymongo import MongoClient
uri = "mongodb://uname:mypass#Someth-pt-ved-01:27017"
client = MongoClient(uri)
db = client.pt
collection = db.devices
#to get single record details
cursor = collection.find({'ID': 1490660})
print(cursor)
#to get all documents from collection-devices
for document in cursor:
print(document)
Note; I am working on Windows 10.

Related

Use Managed Identity to authenticate Azure App Service to SQL Database

I am trying to connect a Python Flask app running in Azure App Service Web App to an Azure SQL Database.
The works just fine when I use SQL authentication with username and password.
Now I want to move to using the Web Apps managed identity.
I have activated the system-assigned managed identity, created a user for it in SQL and added it to the db_datareader role.
I am connecting with SqlAlchemy using a connection string like this
params = urllib.parse.quote_plus(os.environ['SQL_CONNECTION_STRING'])
conn_str = 'mssql+pyodbc:///?odbc_connect={}'.format(params)
engine_azure = db.create_engine(conn_str,echo=True)
The connection string is stored as an application setting, and its value is
"Driver={ODBC Driver 17 for SQL Server};Server=tcp:<server>.database.windows.net,1433;Database=<database>;Authentication=ActiveDirectoryMsi;"
I expected this to be all I need to do, but now my app is not starting.
The logs report a timeout when connecting to the database.
How can I fix this?
I know this is quite an old post, but it may help people like me who are looking for a solution.
You could modify the connection string by adding "Authentication" parameters as "ActiveDirectoryMsi", no need to use endpoint and headers.
(Works with Azure SQL, for other databases like Postgress you may need to use the struct token)
import pyodbc
pyodbc.connect(
"Driver="
+ driver
+ ";Server="
+ server
+ ";PORT=1433;Database="
+ database
+ ";Authentication=ActiveDirectoryMsi")
I wrote a quick article for those who are interested in Azure MSI:
https://hedihargam.medium.com/python-sql-database-access-with-managed-identity-from-azure-web-app-functions-14566e5a0f1a
If you want to connect Azure SQL database with Azure MSI in python application, we can use the SDK pyodbc to implement it.
For example
Enable system-assigned identity for your Azure app service
Add the MSi as contained database users in your database
a. Connect your SQL database with Azure SQL AD admin (I use SSMS to do it)
b. run the following the script in your database
CREATE USER <your app service name> FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER <your app service name>
ALTER ROLE db_datawriter ADD MEMBER <your app service name>
ALTER ROLE db_ddladmin ADD MEMBER <your app service name>
Code
import os
import pyodbc
import requests
import struct
#get access token
identity_endpoint = os.environ["IDENTITY_ENDPOINT"]
identity_header = os.environ["IDENTITY_HEADER"]
resource_uri="https://database.windows.net/"
token_auth_uri = f"{identity_endpoint}?resource={resource_uri}&api-version=2019-08-01"
head_msi = {'X-IDENTITY-HEADER':identity_header}
resp = requests.get(token_auth_uri, headers=head_msi)
access_token = resp.json()['access_token']
accessToken = bytes(access_token, 'utf-8');
exptoken = b"";
for i in accessToken:
exptoken += bytes({i});
exptoken += bytes(1);
tokenstruct = struct.pack("=i", len(exptoken)) + exptoken;
conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};Server=tcp:andyserver.database.windows.net,1433;Database=database2", attrs_before = { 1256:bytearray(tokenstruct) });
cursor = conn.cursor()
cursor.execute("select ##version")
row = cursor.fetchall()
For more details, please refer to the
https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki/Connect-to-Azure-SQL-Database
https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity
https://learn.microsoft.com/en-us/azure/sql-database/sql-database-aad-authentication-configure

Importing python script to zabbix?

So ive made a easy python script to monitor DB sizes in my postgres but now id like to form graphs about the results to be monitored. However i cannot find a single way to get this script into the WEB GUI to be used in zabbix/grafana. We use zabbix and grafana on top of that simply because grafana looks way better.
# pip install psycopg2-binary
import psycopg2
connection = psycopg2.connect(user = "postgres", password = "password", host = "server", port =
"5432", database = "postgres")
cursor = connection.cursor()
cursor.execute("SELECT datname FROM pg_database WHERE datistemplate = false")
records = cursor.fetchall()
for record in records:
cursor.execute("SELECT pg_size_pretty( pg_database_size('{}'))".format(record[0]))
row = cursor.fetchone()
print("DB:{} Size:{}".format(record[0], row[0]))
Ive been googleing around the entire morning but i cant find any information about this. Ive found that it should be added to /zabbix/externalscripts folder but i did so and now i have no clue how to access it and add to a graph.
You are dealing with multiple databases and for each of them you want the size: you need to implement a Low Level Discovery for your target host.
The discovery rule should produce a json like:
{
"data": [
{
"{#DBNAME}": "Database 1",
"{#SOMEOTHERPROPERTY}": "XXX"
},
{
"{#DBNAME}": "Database 2",
"{#SOMEOTHERPROPERTY}": "YYY"
}
] }
Then you have to create an item prototype which uses {#DBNAME} as a reference, to query the db size.
You can create both the LLD and the item prototype using the ODBC support.
For instance, your OBDC discovery should be:
Key = db.odbc.discovery[get_databases,{HOST.NAME}]
Params = SELECT datname FROM pg_database WHERE datistemplate = false
And your item prototype:
Key = db.odbc.select[Used size on {#datname},{HOST.NAME}]
Params = SELECT pg_size_pretty( pg_database_size('{#datname}'))
After this setup, you will have an item for each database (and new databases will be discovered dynamically): you can plot them with latest data, with Grafana or by defining Graph Prototypes.

Connection mongo with python

I'm trying to connect to a mongo db using python, this is my code:
import pymongo
from pymongo import MongoClient
MONGODB_URI = "mongodb://<user_name>:<user_password>#ds035177.mlab.com:35177<something>"
client = MongoClient(MONGODB_URI, connectTimeoutMS=30000)
db = client.get_default_database("<db_default>")
myDB = db.<collection>
record = {
"user_id" : 1,
"name" : "test",
"college" : "test"
}
myDB.insert_one(record)
For some reason i'm getting timeout and i dont' know why...
Can you connect from command line on your desktop; e.g.
mongo mongodb://<user_name>:<user_password>#ds035177.mlab.com:35177<something>
If not, chances are the server isn't running on port 35177, or port 35177 isn't open, or you haven't allowed external access from the mongo server.

How to query a (Postgres) RDS DB through an AWS Jupyter Notebook?

I'm trying to query an RDS (Postgres) database through Python, more specifically a Jupyter Notebook. Overall, what I've been trying for now is:
import boto3
client = boto3.client('rds-data')
response = client.execute_sql(
awsSecretStoreArn='string',
database='string',
dbClusterOrInstanceArn='string',
schema='string',
sqlStatements='string'
)
The error I've been receiving is:
BadRequestException: An error occurred (BadRequestException) when calling the ExecuteSql operation: ERROR: invalid cluster id: arn:aws:rds:us-east-1:839600708595:db:zprime
In the end, it was much simpler than I thought, nothing fancy or specific. It was basically a solution I had used before when accessing one of my local DBs. Simply import a specific library for your database type (Postgres, MySQL, etc) and then connect to it in order to execute queries through python.
I don't know if it will be the best solution since making queries through python will probably be much slower than doing them directly, but it's what works for now.
import psycopg2
conn = psycopg2.connect(database = 'database_name',
user = 'user',
password = 'password',
host = 'host',
port = 'port')
cur = conn.cursor()
cur.execute('''
SELECT *
FROM table;
''')
cur.fetchall()

How do I use pymongo to connect to an existing document collection/db?

On the command line, this works:
$ mongo
> show dbs
mydatabase 1.0GB
However, this does not:
$ python
>>> import pymongo
>>> connection = pymongo.MongoClient()
>>> connection.mydatabase.find()
I read through docs here:
http://api.mongodb.org/python/current/tutorial.html
But do not understand how to either...
connect to an existing database (using pymongo)
query what databases exist in the mongodb connection.
Why can't I access my database?
Connect to an existing database
import pymongo
from pymongo import MongoClient
connection = MongoClient()
db = connection.mydatabase
List existing databases
import pymongo
from pymongo import MongoClient
connection = MongoClient()
# connection.database_names() # depreciated
connection.list_database_names()
The question implies user has a local MongoDB. However I found this question trying to connect to a remote MongoDB. I think the tutorial is worth mentioning (no other answer here mentioned how I can specify the host and the port)
The above code will connect on the default host and port. We can also specify the host and port explicitly, as follows:
client = MongoClient('localhost', 27017)
Or use the MongoDB URI format:
client = MongoClient('mongodb://localhost:27017/')
show dbs and find() are totally different commands as such you cannot compare the two.
connection.mydatabase.find()
Will actually do nothing because you cannot find() documents on database level. You are probably looking for:
cursor = connection.mydatabase.mycol.find()
I am no Python programmer but something like that and the foreach the cursor var to get your data.
As an added note you will want to replace mycol with the collection name that contains your documents.
As for querying for a list of databases you can do something like:
databases = connection.mydatabase.command({'listDatabases': 1});
As shown here: http://docs.mongodb.org/manual/reference/command/listDatabases/#listDatabases
However again I am no Python programmer but this should get you started.
On the python command line:
import pymongo
from pymongo import MongoClient
connection = MongoClient() ## connects by default to db at localhost:27017
connection.database_names() ## python binding equivalent to show dbs.
Although there doesn't seem to be a wealth of examples, it appears that the bindings are pretty complete within the Python Driver API Documentation.
database_names() is deprecated. One can use list_database_names() instead.
mongo_db_url will be something like "mongodb://localhost:27017/". 27017 is deafult port number, replace suitably.
from pymongo import MongoClient
client = MongoClient(<mongo_db_url>)
#or client = MongoClient('localhost', 27017)
client.list_database_names()

Categories