Get index name of a list made from dictionaries - python

I want to begin by saying that I am by no mean a python expert so I am sorry if I express myself in an incorrect way.
I am building a script that goes something like this:
from netmiko import ConnectHandler
visw0102 = {
'device_type': 'hp_comware',
'ip': '192.168.0.241',
'username': 'admin',
'password': 'password'
}
visw0103 = {
'device_type': 'hp_comware',
'ip': '192.168.0.242',
'username': 'admin',
'password': 'password'
}
site1_switches = [visw0102, visw0103]
for switch in site1_switches:
... (rest of the script)
I am trying to get the current index name in the FOR loop by using the enumerate() function to get the index name of the site1_switches list but since that list is made of dictionary items, the dictionary keys are returned:
>>> for index, w in enumerate(switch):
... print(w)
...
device_type
ip
username
password
Is there a way the get the actual index name (VISW010X) instead of values that are in the dictionaries?
Thank you
Edit: Nested dictionary was the answer here, thanks Life is complex
So I was able to get further. Here's the code now.
from netmiko import ConnectHandler
site1_switches = {
'visw0102' : {
'device_type': 'hp_comware',
'ip': '192.168.0.241',
'username': 'admin',
'password': 'password'
},
'visw0103' : {
'device_type': 'hp_comware',
'ip': '192.168.0.242',
'username': 'admin',
'password': 'password'
}
}
for key, values in site1_switches.items():
device_type = values.get('device_type', {})
ip_address = values.get('ip', {})
username = values.get('username', {})
password = values.get('password', {})
for key in site1_switches.items():
net_connect = ConnectHandler(**dict(key)) <- The ConnectHandler needs a dictionary
Now the problem is that the dictionary key seems to be converted to a tuple but the ConnectHandler module needs a dictionary to proceed.
Here's what I get:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: dictionary update sequence element #0 has length 8; 2 is required
I would need to find a way to convert the tuple to a dictionary but it seems that dict(key) doesn't work as it puts the tuple in the first dictionary key (or so it seems).
Anyway I can achieve that?
Thanks!

Have you considered using a nested dictionary?
site1_switches = {
'visw0102': {
'device_type': 'hp_comware',
'ip': '192.168.0.241',
'username': 'admin',
'password': 'password'
},
'visw0103': {
'device_type': 'hp_comware',
'ip': '192.168.0.242',
'username': 'admin',
'password': 'password'
}}
for key, value in site1_switches.items():
print (key)
# output
visw0102
visw0103
Here's another way to accomplish this.
for index, (key, value) in enumerate(site1_switches.items()):
print(index, key, value)
# output
0 visw0102 {'device_type': 'hp_comware', 'ip': '192.168.0.241', 'username': 'admin', 'password': 'password'}
1 visw0103 {'device_type': 'hp_comware', 'ip': '192.168.0.242', 'username': 'admin', 'password': 'password'}
A more complete solution
from netmiko import ConnectHandler
# nested dictionary
site1_switches = {
'visw0102': {
'device_type': 'hp_comware',
'ip': '192.168.0.241',
'username': 'admin',
'password': 'password'
},
'visw0103': {
'device_type': 'hp_comware',
'ip': '192.168.0.242',
'username': 'admin',
'password': 'password'
}}
for key, values in site1_switches.items():
device_type = values.get('device_type', {})
ip_address = values.get('ip', {})
username = values.get('username', {})
password = values.get('password', {})
print (f'{key}', {device_type}, {ip_address}, {username}, {password})
# output
visw0102 {'hp_comware'} {'192.168.0.241'} {'admin'} {'password'}
visw0103 {'hp_comware'} {'192.168.0.242'} {'admin'} {'password'}
print (f'Establishing a connection to {key}')
# output
Establishing a connection to visw0102
# pseudo code based on ConnectHandler parameters
switch_connect = ConnectHandler(device_type=device_type, host=ip_address, username=username, password=password)
# checking that the connection has a prompt
switch_connect.find_prompt()
# What you want to do goes here...
# Example
command_output = switch_connect.send_command('display current-configuration')

Unfortunately, there doesn't seem to be a nice, succinct way of accessing the dictionary's name, but Get name of dictionary provides some possible workarounds:
Nesting your switch dictionaries within an overarching dictionary that maps names to dictionaries is one method.
site1_switches = {
"visw0102": visw0102,
"visw0103": visw0103
}
Another would be to add a "name" key to each dictionary, so that you can access the names of each switch in site1_switches by switch['name']
visw0102 = {
'name': 'visw0102',
'device_type': 'hp_comware',
'ip': '192.168.0.241',
'username': 'admin',
'password': 'password'
}
visw0103 = {
'name': 'visw0103',
'device_type': 'hp_comware',
'ip': '192.168.0.242',
'username': 'admin',
'password': 'password'
}

Related

How to extract value inside a dictionary inside nested list

I am getting below error as I try to access the value for "hostname" key inside a dictionary
TypeError: list indices must be integers or slices, not str
This is the content of hostnames = result.json()
{
'accountId': 'act_1234',
'contractId': 'ctr_1234',
'groupId': 'grp_1234',
'propertyId': 'prp_1234',
'propertyName': 'www.property.com',
'propertyVersion': 1,
'etag': 'jbcas6764023nklf78354',
'rules': {
'name': 'default',
'children': [{
'name': 'Route',
'children': [],
'behaviors': [{
'name': 'origin',
'options': {
'originType': 'CUSTOMER',
'hostname': 'www.origin.com',
'forwardHostHeader': 'REQUEST_HOST_HEADER',
my code looks like this
#get hostnames of each property
for (j, k) in itertools.zip_longest(propid, prodversion):
propertyId = str(j)
propertyVersion = str(k)
path= '/sample/v1/properties/{}/versions/{}/rules'.format(propertyId, propertyVersion)
headers = {
"Accept": "application/json",
"PAPI-Use-Prefixes": "true"
}
querystring = {
"contractId": "ctr_1234",
"groupId": str(i),
"validateRules": "true",
"validateMode": "full"
}
result = session.get(urljoin(baseurl, path), headers=headers, params=querystring, verify=False)
hostnames = result.json()
hostnameslist = [host['hostname'] for host in hostnames['rules']['children']['behaviors']['options']]
print(hostnameslist)
my desired outcome would be a list of propertyName and its corresponding hostnames (could be multiple)
'properties': {
'www.property1.com': ['www.origin1.com', 'www.origin2.com'],
'www.property2.com': ['www.origin1.com', 'www.origin2.com']
}
seems that you have an array in "behaviors" value so you need to go into the array like this:
hostnameslist = [host['hostname'] for host in hostnames['rules']['children']['behaviors'][0]['options']]

How to differentiate access to data at the database server level?

In DB i have three roles: guest, client and admin.
In my django project, there are three connections under these roles
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'test',
'USER': 'guest',
'PASSWORD': 'guest',
'HOST': 'localhost',
'PORT': 5432,
},
'admin': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'test',
'USER': 'admin',
'PASSWORD': 'admin',
'HOST': 'localhost',
'PORT': 5432,
},
'customer': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'test',
'USER': 'customer',
'PASSWORD': 'customer',
'HOST': 'localhost',
'PORT': 5432,
}
}
How and where can I change the connection to the database depending on whether the user is authenticated or not?
I am presuming that you are using psycopg2 to connect to the Postgresql RDBMS. What I would do is specify what Postgresql user you want to use before you execute your query.
For example:
import psycopg2
def func1():
conn = psycopg2.connect(database = "exampledb", user = "user1", password = "user1password", host = "127.0.0.1", port = "5432")
cur = conn.cursor()
cur.execute("SELECT * FROM schema_name.table_name;")
rows = cur.fetchall()
for row in rows:
print(row)
def func2():
conn = psycopg2.connect(database = "exampledb", user = "user2", password = "user2password", host = "127.0.0.1", port = "5432")
cur = conn.cursor()
cur.execute("INSERT INTO schema_name.table_name (col1, col2) VALUES(1, 2);")
rows = cur.fetchall()
for row in rows:
print(row)
I would also be very careful with the admin user, from a security standpoint I would not allow this account to be used for the server-side scripting, this is because if and sql injection is executed, then a lot of harm could be caused. For prevention of sql injections in python I would recommend this: https://realpython.com/prevent-python-sql-injection/

Using quicksight boto3 update_data_source

Summary
What is the right syntax to use update_data_source Quicksight boto3 to change credentials ?
Context
I am trying to use update data source method for Quicksight on boto3 to update my Redshift credentials in Quicksight.
My issue is that it is passing a dictionary as key to another dictionary. How can I unpack that to get to the username / password for Redshift ?
Code
My code looks like this :
def main():
qs = boto3.client('quicksight', region_name=region_name)
response = qs.update_data_source(
AwsAccountId='awsaccountid',
DataSourceId='datasourceid',
Name='qs_test',
Credentials={
{
'CredentialPair':{
'Username': 'test_user'
'Password': 'my_pass'
}
}
}
)
print(response)
main()
Also tried the below
response = qs.update_data_source(
AwsAccountId='awsaccountid',
DataSourceId='datasourceid',
Name='qs_test',
Credentials={CredentialPair
{
RedshiftParameters=[
{
'Database': 'dbname',
'ClusterId': 'clusterid'
}
}
],
Credentials={
'CredentialPair': {
'Username': 'test_user',
'Password': 'my_pass'
}
}
)
print(response)
The below syntax works :
def main():
qs = boto3.client('quicksight', region_name=region_name)
response = qs.update_data_source(
AwsAccountId='awsaccountid',
DataSourceId='datasourceid',
Name='qs_test',
DataSourceParameters={
'RedshiftParameters'={
'Database': 'dbname',
'ClusterId': 'clusterid'
}
}
}
Credentials={
'CredentialPair':{
'Username': 'test_user'
'Password': 'my_pass'
}
}
)
print(response)
main()

problems with requests in python list

I am going to post phone in the app but I am getting error again and again. Because the structure of the post looks like that
data = {
'login': 'login',
'password': 'password',
'data': '[{"user_id": "user_id","text": "key"}]'
}
response = requests.post('url', data=data)
the problem with this code is that user_id and key because they are not default values they can be different. if I remove apostrophe from the list. Error occurs Array is not Json. If I put this like that
data = [
{
'login': 'login',
'password': 'password',
'data': {"user_id": user_id, "text": key}
}
]
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
response = requests.post('url', json=data, headers=headers)
It throws another error Login or Password is null. How can I solve this problems any help plz? thank you in advance!
If I understand the question correctly, you want to replace the hard-coded user id and key with values from a pair of variables. This shouldn't require any change in the structure of the payload. Just try
import json
user_id = "..."
key = "..."
request_data = [{"user_id": user_id, "text": key}]
data = {
'login': 'login',
'password': 'password',
'data': json.dump(request_data)
}
response = requests.post('url', data=data)

Use dictionary keys in FOR loop to specify a list

I am trying to specify a list in a for loop using the keys from a dictionary added to a string. Let me explain:
site1_switches = {
'visw0102' : {
'device_type': 'hp_comware',
'ip': '192.168.0.241',
'username': 'admin',
'password': 'password'
},
'visw0103' : {
'device_type': 'hp_comware',
'ip': '192.168.0.242',
'username': 'admin',
'password': 'password'
},
'visw0105' : {
'device_type': 'hp_comware',
'ip': '192.168.0.244',
'username': 'admin',
'password': 'password'
}
}
uplinks_visw0102 = ['GigabitEthernet1/0/1','GigabitEthernet1/0/2']
uplinks_visw0103 = ['GigabitEthernet1/0/48']
uplinks_visw0105 = ['GigabitEthernet1/0/1','GigabitEthernet1/0/48']
for key, values in site1_switches.items():
for port in ('uplinks_' + key):
print(port)
Now this is not all the script but it's the part I am stuck at with the elements needed for it to run as it is.
I was expecting port to contain uplinks_visw010X depending on where it is at in the loop. Instead, here's what I am getting:
>>> for key, values in site1_switches.items():
... for port in ('uplinks_' + key):
... print(port)
...
u
p
l
i
n
k
s
_
v
i
s
w
0
1
0
2
u
p
l
i
n
k
s
_
v
i
s
w
0
1
0
3
u
p
l
i
n
k
s
_
v
i
s
w
0
1
0
5
>>>
It seems that evey character in port is processed by the loop but it's not what I want it to do.
How should the keys be processed for them to, when combined with a string, come out as I expect them to (uplinks_visw010X).
Thank you for your help
eval() is something that you require here. The eval function lets a Python program run Python code within itself. One of useful applications of eval() is to evaluate python expressions from string.
You can update your code, to make use of eval() like this:
>>> for key, values in site1_switches.items():
... for port in eval('uplinks_' + key):
... print(port)
...
GigabitEthernet1/0/1
GigabitEthernet1/0/2
GigabitEthernet1/0/48
GigabitEthernet1/0/1
GigabitEthernet1/0/48

Categories