Skip to content

Commit

Permalink
broken out juniperscript into more readable modules
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesgreen-moj committed Dec 1, 2023
1 parent 16dae5c commit 1992522
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ env/
*.code-workspace
*.sha256
terraform.tfstate

test_data/**.csv
./idea/*
**/__pycache__/
33 changes: 33 additions & 0 deletions src/geocode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from geopy import Nominatim
from timezonefinder import TimezoneFinder

def geocode(address) -> str:
geolocator = Nominatim(user_agent="geocode")
location = geolocator.geocode(address)
try:
latitude, longitude = location.latitude, location.longitude
except ValueError:
raise ValueError('geocode unable to find latitude & longitude for {address}'.format(address=address))
return latitude, longitude

def find_country_code(gps) -> tuple:
latitude = gps[0]
longitude = gps[1]
geolocator = Nominatim(user_agent="geocode")
location = geolocator.reverse([latitude, longitude])
country_code=location.raw['address']['country_code']

return country_code.upper()

def find_timezone(gps) -> tuple:
tf_init = TimezoneFinder()
latitude = gps[0]
longitude = gps[1]
try:
timezone_name = tf_init.timezone_at(lat=latitude, lng=longitude)
except ValueError:
raise ValueError('The coordinates were out of bounds {latitude}:{longitude}'.format(lat=latitude,lng=longitude))
if timezone_name is None:
raise ValueError('GPS coordinates did not match a time_zone')

return timezone_name
127 changes: 127 additions & 0 deletions src/juniper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import sys, requests, json

# Mist CRUD operations
class Admin(object):
def __init__(self, token=''):
self.session = requests.Session()
self.headers = {
'Content-Type': 'application/json',
'Authorization': 'Token ' + token
}

def post(self, url, payload, timeout=60):
url = 'https://api.eu.mist.com{}'.format(url)
session = self.session
headers = self.headers

print('POST {}'.format(url))
response = session.post(url, headers=headers, json=payload)

if response.status_code != 200:
print('Failed to POST')
print('\tURL: {}'.format(url))
print('\tPayload: {}'.format(payload))
print('\tResponse: {} ({})'.format(response.text, response.status_code))

return False

return json.loads(response.text)

def put(self, url, payload):
url = 'https://api.eu.mist.com{}'.format(url)
session = self.session
headers = self.headers

print('PUT {}'.format(url))
response = session.put(url, headers=headers, json=payload)

if response.status_code != 200:
print('Failed to PUT')
print('\tURL: {}'.format(url))
print('\tPayload: {}'.format(payload))
print('\tResponse: {} ({})'.format(response.text, response.status_code))

return False

return json.loads(response.text)


# Main function
def juniper_script(
data,
mist_api_token='',
org_id=''):

show_more_details = True # Configure True/False to enable/disable additional logging of the API response objects


# Check for required variables
if mist_api_token == '':
print('Please provide your Mist API token as mist_api_token')
sys.exit(1)
elif org_id == '':
print('Please provide your Mist Organization UUID as org_id')
sys.exit(1)

# Establish Mist session
admin = Admin(mist_api_token)

# Create each site from the CSV file
for d in data:
# Variables
site_id = None
site = {'name': d.get('Site Name', ''),
'address': d.get('Site Address', ''),
"latlng": {"lat": d.get('gps', '')[0], "lng": d.get('gps', '')[1]},
"country_code": d.get('country_code', ''),
"timezone": d.get('time_zone', ''),
}

# MOJ specific attributes
site_setting = {

"vars": {
"Enable GovWifi": d.get('Enable GovWifi', ''),
"Enable MoJWifi": d.get('Enable MoJWifi', ''),
"Wired NACS Radius Key": d.get('Wired NACS Radius Key', ''),
"GovWifi Radius Key": d.get('GovWifi Radius Key', '')

}

}



print('Calling the Mist Create Site API...')
result = admin.post('/api/v1/orgs/' + org_id + '/sites', site)
if result == False:
print('Failed to create site {}'.format(site['name']))
print('Skipping remaining operations for this site...')
print('\n\n==========\n\n')

continue
else:
site_id = result['id']
print('Created site {} ({})'.format(site['name'], site_id))

if show_more_details:
print('\nRetrieving the JSON response object...')
print(json.dumps(result, sort_keys=True, indent=4))
print('\nUsing id in the Mist Update Setting API request')

print()

# Update Site Setting
print('Calling the Mist Update Setting API...')
result = admin.put('/api/v1/sites/' + site_id + '/setting',
site_setting)
if result == False:
print('Failed to update site setting {} ({})'.format(site['name'], site_id))
else:
print('Updated site setting {} ({})'.format(site['name'], site_id))

if show_more_details:
print('\nRetrieving the JSON response object...')
print(json.dumps(result, sort_keys=True, indent=4))

print('\n\n==========\n\n')
49 changes: 49 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from juniper import juniper_script
import os, csv
from geocode import geocode, find_timezone, find_country_code


# Convert CSV file to JSON object.
def csv_to_json(file_path):
csv_rows = []
with open(file_path) as csvfile:
reader = csv.DictReader(csvfile, skipinitialspace=True, quotechar='"')
title = reader.fieldnames

for row in reader:
csv_rows.extend([ {title[i]: row[title[i]] for i in range(len(title))} ])

return csv_rows

if __name__ == '__main__':

csv_file_path=os.getcwd() + '/../test_data/sites_with_clients.csv'

# Convert CSV to valid JSON
data = csv_to_json(csv_file_path)
if data == None or data == []:
raise ValueError('Failed to convert CSV file to JSON. Exiting script.')


# Create each site from the CSV file
for d in data:
# Variables
site_id = None
site = {'name': d.get('Site Name', ''),
'address': d.get('Site Name', '')
}

gps = geocode(d.get('Site Address', ''))
country_code = find_country_code(gps)
time_zone = find_timezone(gps)

# Adding new key-value pairs to the dictionary
d['gps'] = gps
d['country_code'] = country_code
d['time_zone'] = time_zone

juniper_script(
mist_api_token=os.environ['MIST_API_TOKEN'],
org_id=os.environ['ORG_ID'],
data=data
)
3 changes: 3 additions & 0 deletions src/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
requests==2.21.0
geopy==2.4.1
timezonefinder==6.2.0
Empty file added test_data/.gitkeep
Empty file.

0 comments on commit 1992522

Please sign in to comment.