# Adding some config to a juniper device

I wrote this script to add some config to a Juniper device. It works well but the whole user input validation section (yes or no section) seems a little messy.

Is there a better way I could have done it?

from jnpr.junos import Device
from jnpr.junos.utils.config import Config
import getpass

#Grab credentials

#Confirmation of commands
commands = open("commands" , "r")
print ""
print "The commands you are about to commit are: "
print commands_to_commit
print ""
print "Do you want to continue to run these commands?"
confirm = raw_input("Y or N: ")
if confirm in ['n','no','N','NO','No']:
print "Exiting..."
quit()
while confirm not in ['y','Y','yes',"Yes",'YES','n','N','NO','No','no']:
print "Invalid Choice, Try again"
confirm = raw_input("Y or N: ")
if confirm in ['n','no','N','NO','No']:
print "Exiting..."
quit()
elif confirm in ['y','Y','yes',"Yes",'YES']:
continue

#Open a file called swichlist which has a list of devices to modify
with open('switchlist') as infile:
for host in infile:
try:
print "Working on:", host,
#Connect to devices in switchlist
dev.open()
cu = Config(dev)
#Looks for a file named commands with the list of commands to run
incmd = open('commands')
cu.commit()
dev.close()
print "Completed:", host
except Exception,e: print "Error:", e
continue


## migrated from stackoverflow.comJul 29 '15 at 17:28

This question came from our site for professional and enthusiast programmers.

• Please correct your indentation. The code is technically broken as posted in Rev 1. – 200_success Jul 29 '15 at 17:47

The confirmation prompt is a self-contained chunk of code with a specific purpose. It deserves to be extracted into a function:

def confirm(prompt='Y or N: ', yes='YES', no='NO'):
while True:
response = raw_input(prompt).upper()
if yes.startswith(response) and not no.startswith(response):
return True
elif no.startswith(response) and not yes.startswith(response):
return False
print "Invalid choice. Try again."


(Technically, this is more lenient than your original code, in that it accepts strings like 'yE' as a yes. I think that's OK.)

Then, in your main program, you can write:

print "Do you want to continue to run these commands?"
if not confirm():
print "Exiting..."
quit()


Any call to open() should almost certainly be done using a with block. You wrote with open('switchlist') as infile, which is good. However, you also wrote commands = open("commands", "r") and incmd = open('commands'), neither of which you close properly. But why are you calling incmd = open('commands') at all, when it's just supposed to be commands_to_commit?

• If you allow any string for yes and no, you should reject an answer which is a prefix of the longest common prefix among yes and no (and any other valid answer). Example, if yes='fantastic' and no='false', the longest common prefix is 'fa', and any answer prefix of this (namely 'f' and 'fa') is ambiguous, but your code will treat it as a yes answer. – fferri Jul 29 '15 at 20:52
• Also note that for any string s, s.startswith('') is always true, so you treat also the empty answer as yes. – fferri Jul 29 '15 at 20:53

If you .lower() the input you have to match it against less patterns. Also a single while loop can handle all the input validation stuff.

while True: # repeat until input is not valid
confirm = raw_input("Y or N: ").lower()
if confirm in ('y', 'yes', 'n', 'no'): break
else: print "Invalid Choice, Try again"

if confirm in ('n', 'no'):
print "Exiting..."
quit()


You can get rid of the first:

confirm = raw_input("Y or N: ").lower()
if confirm in ['n', 'no']:
print "Exiting..."
quit()


right off the bat. Just initialize confirm to ''and it'll kick you into the while loop.

You can also move the 'switchlist' and 'commands' filenames to variables so they aren't hard coded. Ideally, you should move them to a config file or cli args.

Below is the updated/cleaned up version of your code:

from jnpr.junos import Device
from jnpr.junos.utils.config import Config
import getpass

commands_filename = 'commands'
switchlist_filename = 'switchlist'

# Grab credentials

# Confirmation of commands

print ''
print 'The commands you are about to commit are: '
print commands_to_commit
print ''
print 'Do you want to continue to run these commands?'

confirm = ''
while confirm not in ['y', 'ye', 'yes', 'n', 'no']:
confirm = raw_input('Y or N: ').lower()
if confirm in ['n', 'no']:
print 'Exiting...'
quit()
elif confirm in ['y', 'ye', 'yes']:
continue
else:
print 'Invalid choice, try again'

# Open a file called swichlist which has a list of devices to modify
with open(switchlist_filename) as infile:
for host in infile:
try:
print 'Working on: ', host

# Connect to devices in switchlist
dev.open()
cu = Config(dev)

# Looks for a file named commands with the list of commands to run