diff --git a/.codacy.yml b/.codacy.yml
index 0701063..ecc3b91 100644
--- a/.codacy.yml
+++ b/.codacy.yml
@@ -1,6 +1,5 @@
---
exclude_paths:
- 'aiojss/**'
- - 'tools/**'
- 'scripts/**'
- 'extension_attributes/**'
diff --git a/.gitignore b/.gitignore
index ed50ea2..0666066 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,6 @@ extension_attributes/*
!extension_attributes/Last User/
scripts/*
!scripts/Install Software Updates/
+!scripts/templates
+!extension_attributes/templates
+tools/ci_tests/computers.json
diff --git a/README.md b/README.md
index 597bf78..52a7023 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# git2jss
-[![Codacy Badge](https://api.codacy.com/project/badge/Grade/d9d618c32e93436ea67102fd3d3f5b21)](https://www.codacy.com/app/adam-furbee/git2jss?utm_source=github.com&utm_medium=referral&utm_content=BadStreff/git2jss&utm_campaign=Badge_Grade)
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/c49c0bd6a88d4f1e8c6808455171178e)](https://app.codacy.com/gh/rustymyers/git2jss/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
A fast asynchronous python library for syncing your scripts in git with your JSS easily. This allows admins to keep their script in a version control system for easy updating rather than googling and copy-pasting from resources that they find online.
@@ -26,16 +26,16 @@ Optional flags for `sync.py`:
- `--verbose` to add additional logging
- `--update_all` to upload all resources in `./extension_attributes` and `./scripts`
- `--jenkins` to write a Jenkins file:`jenkins.properties` with `$scripts` and `$eas` and compare `$GIT_PREVIOUS_COMMIT` with `$GIT_COMMIT`
-
-### [ConfigParser](https://docs.python.org/3/library/configparser.html) (Optional):
-
-A config file can be created in the project root or the users home folder. When a config file exists, the script will not promt for a password.
-
- A jamfapi.cfg file can provide the following variables:
-
- - username
- - password
- - url
+
+### [ConfigParser](https://docs.python.org/3/library/configparser.html) (Optional):
+
+A config file can be created in the project root or the users home folder. When a config file exists, the script will not promt for a password.
+
+ A jamfapi.cfg file can provide the following variables:
+
+- username
+- password
+- url
### Prerequisites
git2jss requires [Python 3.6](https://www.python.org/downloads/) and the python modules listed in `requirements.txt`
diff --git a/extension_attributes/templates/Last User/ea.sh b/extension_attributes/templates/Last User/ea.sh
new file mode 100644
index 0000000..059b4d3
--- /dev/null
+++ b/extension_attributes/templates/Last User/ea.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+lastUser=`defaults read /Library/Preferences/com.apple.loginwindow lastUserName`
+
+if [ $lastUser == "" ]; then
+ echo "No logins"
+else
+ echo "$lastUser"
\ No newline at end of file
diff --git a/extension_attributes/templates/Last User/ea.xml b/extension_attributes/templates/Last User/ea.xml
new file mode 100644
index 0000000..8195681
--- /dev/null
+++ b/extension_attributes/templates/Last User/ea.xml
@@ -0,0 +1,13 @@
+
+
+ Last User
+ true
+ This attribute displays the last user to log in. This attribute applies to both Mac and Windows.
+ String
+
+ script
+ Mac
+
+
+ General
+
diff --git a/requirements.txt b/requirements.txt
index c201a9a..95ed3b5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,4 +3,5 @@ cchardet
aiodns
uvloop
requests
-configparser
\ No newline at end of file
+configparser
+defusedxml
\ No newline at end of file
diff --git a/scripts/templates/Install Software Updates/script.sh b/scripts/templates/Install Software Updates/script.sh
new file mode 100644
index 0000000..827e16e
--- /dev/null
+++ b/scripts/templates/Install Software Updates/script.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Install all software updates
+# Example for git2jss
+
+softwareupdate -i -a
+
+exit 0
\ No newline at end of file
diff --git a/scripts/templates/Install Software Updates/script.xml b/scripts/templates/Install Software Updates/script.xml
new file mode 100644
index 0000000..ce83c38
--- /dev/null
+++ b/scripts/templates/Install Software Updates/script.xml
@@ -0,0 +1,11 @@
+
+
diff --git a/sync.py b/sync.py
index f39f433..7005c8d 100755
--- a/sync.py
+++ b/sync.py
@@ -4,7 +4,6 @@
import os
from os.path import dirname, join, realpath
import sys
-import xml.etree.ElementTree as ET
import getpass
import argparse
import logging
@@ -14,8 +13,7 @@
import uvloop
import configparser
import requests
-import configparser
-import requests
+from defusedxml import ElementTree as eTree
logging.basicConfig(
level=logging.DEBUG,
@@ -40,7 +38,7 @@ def get_uapi_token():
fetches api token
"""
jamf_test_url = url + "/api/v1/auth/token"
- response = requests.post(url=jamf_test_url, auth=(username, password))
+ response = requests.post(url=jamf_test_url, auth=(username, password), timeout=5)
response_json = response.json()
return response_json["token"]
@@ -51,27 +49,7 @@ def invalidate_uapi_token(uapi_token):
"""
jamf_test_url = url + "/api/v1/auth/invalidate-token"
headers = {"Accept": "*/*", "Authorization": "Bearer " + uapi_token}
- _ = requests.post(url=jamf_test_url, headers=headers)
-
-
-# https://github.com/lazymutt/Jamf-Pro-API-Sampler/blob/5f8efa92911271248f527e70bd682db79bc600f2/jamf_duplicate_detection.py#L99
-def get_uapi_token():
- """
- fetches api token
- """
- jamf_test_url = url + "/api/v1/auth/token"
- response = requests.post(url=jamf_test_url, auth=(username, password))
- response_json = response.json()
- return response_json["token"]
-
-
-def invalidate_uapi_token(uapi_token):
- """
- invalidates api token
- """
- jamf_test_url = url + "/api/v1/auth/invalidate-token"
- headers = {"Accept": "*/*", "Authorization": "Bearer " + uapi_token}
- _ = requests.post(url=jamf_test_url, headers=headers)
+ _ = requests.post(url=jamf_test_url, headers=headers, timeout=5)
def check_for_changes():
@@ -208,7 +186,7 @@ async def upload_extension_attribute(session, url, user, passwd, ext_attr, semap
if has_script and data:
template.find("input_type/script").text = data
if args.verbose:
- print(ET.tostring(template))
+ print(eTree.tostring(template))
print("response status initial get: ", resp.status)
if resp.status == 200:
put_url = (
@@ -217,12 +195,12 @@ async def upload_extension_attribute(session, url, user, passwd, ext_attr, semap
+ template.find("name").text
)
resp = await session.put(
- put_url, data=ET.tostring(template), headers=headers
+ put_url, data=eTree.tostring(template), headers=headers
)
else:
post_url = url + "/JSSResource/computerextensionattributes/id/0"
resp = await session.post(
- post_url, data=ET.tostring(template), headers=headers
+ post_url, data=eTree.tostring(template), headers=headers
)
if args.verbose:
print("response status: ", resp.status)
@@ -248,7 +226,7 @@ async def get_ea_template(session, url, user, passwd, ext_attr):
with open(
join(sync_path, "extension_attributes", ext_attr, xml_file[0]), "r"
) as file:
- template = ET.fromstring(file.read())
+ template = eTree.parse(file.read())
except IndexError:
with async_timeout.timeout(args.timeout):
headers = {
@@ -268,15 +246,17 @@ async def get_ea_template(session, url, user, passwd, ext_attr):
+ ext_attr,
headers=headers,
) as response:
- template = ET.fromstring(await response.text())
+ template = eTree.fromstring(await response.text())
else:
- template = ET.parse(join(sync_path, "templates/ea.xml")).getroot()
+ template = eTree.parse(
+ join(sync_path, "templates/ea.xml")
+ ).getroot()
# name is mandatory, so we use the foldername if nothing is set in
# a template
if args.verbose:
- print(ET.tostring(template))
+ print(eTree.tostring(template))
if template.find("category") and template.find("category").text not in CATEGORIES:
- ET.SubElement(template, "category").text = "None"
+ eTree.SubElement(template, "category").text = "None"
if args.verbose:
c = template.find("category").text
print(
@@ -284,7 +264,7 @@ async def get_ea_template(session, url, user, passwd, ext_attr):
setting to None"""
)
if template.find("name") is None:
- ET.SubElement(template, "name").text = ext_attr
+ eTree.SubElement(template, "name").text = ext_attr
elif not template.find("name").text or template.find("name").text is None:
template.find("name").text = ext_attr
return template
@@ -344,12 +324,12 @@ async def upload_script(session, url, user, passwd, script, semaphore):
url + "/JSSResource/scripts/name/" + template.find("name").text
)
resp = await session.put(
- put_url, data=ET.tostring(template), headers=headers
+ put_url, data=eTree.tostring(template), headers=headers
)
else:
post_url = url + "/JSSResource/scripts/id/0"
resp = await session.post(
- post_url, data=ET.tostring(template), headers=headers
+ post_url, data=eTree.tostring(template), headers=headers
)
if resp.status in (201, 200):
print("Uploaded script: %s" % template.find("name").text)
@@ -369,7 +349,7 @@ async def get_script_template(session, url, user, passwd, script):
]
try:
with open(join(sync_path, "scripts", script, xml_file[0]), "r") as file:
- template = ET.fromstring(file.read())
+ template = eTree.fromstring(file.read())
except IndexError:
with async_timeout.timeout(args.timeout):
headers = {
@@ -384,14 +364,14 @@ async def get_script_template(session, url, user, passwd, script):
async with session.get(
url + "/JSSResource/scripts/name/" + script, headers=headers
) as response:
- template = ET.fromstring(await response.text())
+ template = eTree.fromstring(await response.text())
else:
- template = ET.parse(
+ template = eTree.parse(
join(sync_path, "templates/script.xml")
).getroot()
# name is mandatory, so we use the filename if nothing is set in a template
if args.verbose:
- print(ET.tostring(template))
+ print(eTree.tostring(template))
if (
template.find("category") is not None
and template.find("category").text not in CATEGORIES
@@ -404,7 +384,7 @@ async def get_script_template(session, url, user, passwd, script):
setting to None"""
)
if template.find("name") is None:
- ET.SubElement(template, "name").text = script
+ eTree.SubElement(template, "name").text = script
elif not template.find("name").text or template.find("name").text is None:
template.find("name").text = script
return template
@@ -427,7 +407,7 @@ async def get_existing_categories(session, url, user, passwd, semaphore):
c.find("name").text
for c in [
e
- for e in ET.fromstring(await resp.text()).findall(
+ for e in eTree.fromstring(await resp.text()).findall(
"category"
)
]
@@ -490,26 +470,23 @@ async def main():
CONFIG_FILE = config_path
if CONFIG_FILE != "":
- try:
- # Get config
- CONFPARSER.read(CONFIG_FILE)
- except:
- print("Can't read config file")
+ # Get config
+ CONFPARSER.read(CONFIG_FILE)
try:
username = CONFPARSER.get("jss", "username")
- except:
+ except configparser.NoOptionError:
print("Can't find username in configfile")
try:
password = CONFPARSER.get("jss", "password")
- except:
+ except configparser.NoOptionError:
print("Can't find password in configfile")
try:
url = CONFPARSER.get("jss", "server")
- except:
+ except configparser.NoOptionError:
print("Can't find url in configfile")
try:
sync_path = CONFPARSER.get("jss", "sync_path")
- except:
+ except configparser.NoOptionError:
print("Can't find sync_path in config")
# Ask for password if not supplied via command line args
@@ -537,3 +514,6 @@ async def main():
warnings.simplefilter("always", ResourceWarning)
loop.run_until_complete(main())
+
+ # Remove token
+ invalidate_uapi_token(token)
diff --git a/tools/ci_tests/validate_files_and_folders.sh b/tools/ci_tests/validate_files_and_folders.sh
old mode 100644
new mode 100755
index 7433be8..81d113c
--- a/tools/ci_tests/validate_files_and_folders.sh
+++ b/tools/ci_tests/validate_files_and_folders.sh
@@ -5,20 +5,20 @@
#Load up some variables
#Define scripts and templates folders
-scripts=$(ls -p scripts | grep -v '/$' | sed -e 's/\..*$//')
-scripts_templates=$(ls -p scripts/templates/| sed -e 's/\..*$//')
+scripts=$(ls -1 scripts | grep -v "templates")
+scripts_templates=$(ls -1 scripts/templates/)
#Define EA and templates
-extensionattributes=$(ls -p extension_attributes | grep -v '/$' | sed -e 's/\..*$//')
-extensionattributes_templates=$(ls -p extension_attributes/templates/| sed -e 's/\..*$//')
+extensionattributes=$(ls -1 extension_attributes | grep -v "templates")
+extensionattributes_templates=$(ls -1 extension_attributes/templates/)
#Validate both the Script and the Template for the Script exist.
-echo "Making sure files exist in both places in scripts and scripts/Templates"
+echo "Making sure files with same names exist in both places in scripts and scripts/Templates"
scriptcompare=$(sdiff -bBWsw 75 <(echo "$scripts") <(echo "$scripts_templates" ))
if [ "$scriptcompare" == "" ]; then
- echo "Script and Script Template Exist All good in the hood!"
+ echo "Script and Script Template Exist in both folders!"
else
echo "Errors! occurred please correct the below"
echo " Scripts | Templates"
@@ -31,10 +31,10 @@ fi
#Valate both the EA and the Template for the EA exist.
-echo "Making sure files exist in both places extension_attributes and extension_attributes/Templates"
+echo "Making sure files with same names exist in both places extension_attributes and extension_attributes/Templates"
eacompare=$(sdiff -bBWsw 75 <(echo "$extensionattributes") <(echo "$extensionattributes_templates"))
if [ "$eacompare" == "" ]; then
- echo "EA and EA Template Exist All good in the hood!"
+ echo "EA and EA Template Exist in both folders!"
else
echo "Errors! occurred please correct the below"
echo " Extension Attributes | Templates"
diff --git a/tools/ci_tests/validatexml.sh b/tools/ci_tests/validatexml.sh
old mode 100644
new mode 100755
index b20eaeb..78f203b
--- a/tools/ci_tests/validatexml.sh
+++ b/tools/ci_tests/validatexml.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/zsh
###################################################################################
## Validates XML for proper formatting
###################################################################################
@@ -9,10 +9,10 @@ function scripts() {
printf "\033[31m Working on Scripts\n"
printf "\033[31m---------------------------------------------------------------------------------\n"
printf "\033[0m"
-scriptfolders=$(ls -ltr ./scripts | cut -c52- | awk 'NR>1')
+scriptfolders=$(ls -1 ./scripts | grep -v templates)
while read folder ; do
echo "$folder"
- xmllint --noout ./scripts/"$folder"/*.xml
+ xmllint --noout ./scripts/"$folder"/*.xml
done <<< "$scriptfolders"
}
@@ -20,7 +20,7 @@ scriptfolders=$(ls -ltr ./scripts | cut -c52- | awk 'NR>1')
function ea(){
- eafolders=$(ls -ltr ./extension_attributes | cut -c52- | awk 'NR>1')
+ eafolders=$(ls -1 ./extension_attributes | grep -v templates)
printf "\033[31m---------------------------------------------------------------------------------\n"
printf "\033[31m Working on Extension Attributes\n"
@@ -30,7 +30,7 @@ function ea(){
echo "$folder"
- xmllint --noout ./extension_attributes/"$folder"/*.xml
+ xmllint --noout ./extension_attributes/"$folder"/*.xml
done <<< "$eafolders"
}
diff --git a/tools/ci_tests/verifyEA.py b/tools/ci_tests/verifyEA.py
old mode 100644
new mode 100755
index 8e40a16..43825f9
--- a/tools/ci_tests/verifyEA.py
+++ b/tools/ci_tests/verifyEA.py
@@ -1,60 +1,119 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import requests
-from xml.etree import ElementTree as ET
+from defusedxml import ElementTree as eTree
import os
import getpass
import json
+import configparser
# Use this script to validate that EA values aren't changing as a result of syncing
# Overwrite computers.json
overwrite = False
+smart_group = "1018"
# Constants
-url = 'https://your.jss.com'
-username = getpass.getuser()
-password = getpass.getpass()
+# Get configs from files
+CONFIG_FILE_LOCATIONS = ["jamfapi.cfg", os.path.expanduser("~/jamfapi.cfg")]
+CONFIG_FILE = ""
+# Parse Config File
+CONFPARSER = configparser.ConfigParser()
+for config_path in CONFIG_FILE_LOCATIONS:
+ if os.path.exists(config_path):
+ print("Found Config: {0}".format(config_path))
+ CONFIG_FILE = config_path
+
+if CONFIG_FILE != "":
+ # Get config
+ CONFPARSER.read(CONFIG_FILE)
+ try:
+ username = CONFPARSER.get("jss", "username")
+ password = CONFPARSER.get("jss", "password")
+ url = CONFPARSER.get("jss", "server")
+ smart_group = CONFPARSER.get("verifyEA", "smart_group")
+ except configparser.NoOptionError:
+ print("Can't find configs in configfile")
+ except configparser.NoSectionError:
+ print("Can't find sections in configfile")
+else:
+ url = "https://your.jss.com"
+ username = getpass.getuser()
+ password = getpass.getpass()
+ smart_group = input("Enter smart_group")
+
+
+def get_uapi_token():
+ """
+ fetches api token
+ """
+ jamf_test_url = url + "/api/v1/auth/token"
+ response = requests.post(url=jamf_test_url, auth=(username, password), timeout=5)
+ response_json = response.json()
+ return response_json["token"]
+
+
+def invalidate_uapi_token(uapi_token):
+ """
+ invalidates api token
+ """
+ jamf_test_url = url + "/api/v1/auth/invalidate-token"
+ headers = {"Accept": "*/*", "Authorization": "Bearer " + uapi_token}
+ _ = requests.post(url=jamf_test_url, headers=headers, timeout=5)
-def overwrite_file():
- print('Overwriting File: computers.json...')
- with open('computers.json', 'w') as f:
+def overwrite_file(file_path):
+ print("Overwriting File: computers.json...")
+ with open(file_path, "w") as f:
f.write(json.dumps(computers))
-def read_file():
- print('Reading cached data from disk...')
- with open('computers.json', 'r') as f:
+
+def read_file(file_path):
+ print("Reading cached data from disk...")
+ with open(file_path, "r") as f:
computers_from_disk = json.load(f)
return computers_from_disk
-def build_computers_data_object():
- # Get IDs for computers
- print('Communicating with the Jamf Pro Server...')
+
+def build_computers_data_object(token, group_id):
+ """Builds computer data into local file
+ params: token, group_id
+ returns: computers objects json
+ """
+ print("Communicating with the Jamf Pro Server...")
computers = {}
- r = requests.get(url + '/JSSResource/computergroups/id/810',
- auth = (username, password),
- headers= {'Content-Type': 'application/xml'})
+ r = requests.get(
+ url + "/JSSResource/computergroups/id/{0}".format(group_id),
+ headers={"Content-Type": "application/xml", "Authorization": "Bearer " + token},
+ timeout=5
+ )
- tree = ET.fromstring(r.content)
- resource_ids = [ e.text for e in tree.findall('computers/computer/id') ]
+ tree = eTree.fromstring(r.content)
+ resource_ids = [e.text for e in tree.findall("computers/computer/id")]
# Download each resource and save to disk
for resource_id in resource_ids:
-
# Get detailed information about the record
- r = requests.get(url + '/JSSResource/computers/id/%s' % (resource_id),
- auth = (username, password),
- headers={'Content-Type': 'application/json'})
-
- # Parse xml
- tree = ET.fromstring(r.content)
- ea_values = [ e.text for e in tree.findall('extension_attributes/extension_attribute/value') ]
- ea_names = [ e.text for e in tree.findall('extension_attributes/extension_attribute/name') ]
-
- # Build the json for the comparison
+ r = requests.get(
+ url + "/JSSResource/computers/id/{0}".format(resource_id),
+ headers={"Content-Type": "application/json", "Authorization": "Bearer " + token},
+ timeout=5
+ )
+
+ # Parse xml
+ tree = eTree.fromstring(r.content)
+ ea_values = [
+ e.text
+ for e in tree.findall("extension_attributes/extension_attribute/value")
+ ]
+ ea_names = [
+ e.text
+ for e in tree.findall("extension_attributes/extension_attribute/name")
+ ]
+
+ # Build the json for the comparison
computers[resource_id] = {}
- for k,v in zip(ea_names,ea_values):
+ for k, v in zip(ea_names, ea_values):
computers[resource_id][k] = v
return computers
@@ -67,25 +126,35 @@ def compare_computer(computer_id):
print("Processing Computer ID: %s" % computer_id)
for key in computers[computer_id].keys():
if computers[computer_id][key] != computers_from_disk[computer_id][key]:
- print("Value Change Found\n\tEA Name:\t{}\n\tOriginal Value:\t{}\n\tNew Value:\t{}".format(key,computers[computer_id][key],computers_from_disk[computer_id][key]))
+ print(
+ "Value Change Found\n\tEA Name:\t{}\n\tOriginal Value:\t{}\n\tNew Value:\t{}".format(
+ key,
+ computers[computer_id][key],
+ computers_from_disk[computer_id][key],
+ )
+ )
+
# Is this the first time it was run?
mypath = os.path.dirname(os.path.realpath(__file__))
-if os.path.exists(os.path.join(mypath,'computers.json')):
- computers_from_disk = read_file()
+myfile = os.path.join(mypath, "computers.json")
+if os.path.exists(myfile):
+ computers_from_disk = read_file(myfile)
else:
- print('No cached data found, writing new data to computers.json')
+ print("No cached data found, writing new data to computers.json")
overwrite = True
-# Get computers information from JSS
-computers = build_computers_data_object()
+token = get_uapi_token()
-# Overwrite local file?
-if overwrite == True:
- overwrite_file()
+# Get computers information from JSS smart group
+computers = build_computers_data_object(token, smart_group)
+# Overwrite local file?
+if overwrite:
+ overwrite_file(myfile)
+ print("Computer data staged for comparison with future runs.")
else:
# Compare each computer
- print('Analyzing the results...')
+ print("Analyzing the results...")
for computer_id in list(computers.keys()):
compare_computer(computer_id)
diff --git a/tools/download.py b/tools/download.py
index 6c7545b..02ef580 100755
--- a/tools/download.py
+++ b/tools/download.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import getpass
import requests
-from xml.etree import ElementTree as ET
+from defusedxml import ElementTree as eTree
from xml.dom import minidom
import os
import argparse
@@ -18,7 +18,7 @@ def get_uapi_token():
fetches api token
"""
jamf_test_url = url + "/api/v1/auth/token"
- response = requests.post(url=jamf_test_url, auth=(username, password))
+ response = requests.post(url=jamf_test_url, auth=(username, password), timeout=5)
response_json = response.json()
return response_json["token"]
@@ -29,7 +29,7 @@ def invalidate_uapi_token(uapi_token):
"""
jamf_test_url = url + "/api/v1/auth/invalidate-token"
headers = {"Accept": "*/*", "Authorization": "Bearer " + uapi_token}
- _ = requests.post(url=jamf_test_url, headers=headers)
+ _ = requests.post(url=jamf_test_url, headers=headers, timeout=5)
def download_scripts(
@@ -79,6 +79,7 @@ def download_scripts(
"Authorization": "Bearer " + token,
},
verify=args.do_not_verify_ssl,
+ timeout=5,
)
# Basic error handling
@@ -90,7 +91,7 @@ def download_scripts(
% r.status_code
)
exit(1)
- tree = ET.fromstring(r.content)
+ tree = eTree.fromstring(r.content)
resource_ids = [e.text for e in tree.findall(".//id")]
# Download each resource and save to disk
@@ -105,8 +106,9 @@ def download_scripts(
"Authorization": "Bearer " + token,
},
verify=args.do_not_verify_ssl,
+ timeout=5,
)
- tree = ET.fromstring(r.content)
+ tree = eTree.fromstring(r.content)
if mode == "ea":
if tree.find("input_type/type").text != "script":
@@ -132,7 +134,7 @@ def download_scripts(
# Create script string, and determine the file extension
if get_script:
- xmlstr = ET.tostring(
+ xmlstr = eTree.tostring(
tree.find(script_xml), encoding="unicode", method="text"
).replace("\r", "")
if xmlstr.startswith("#!/bin/sh"):
@@ -166,11 +168,11 @@ def download_scripts(
tree.remove(tree.find("id"))
tree.remove(tree.find("script_contents_encoded"))
tree.remove(tree.find("filename"))
- except:
+ except TypeError:
pass
xmlstr = minidom.parseString(
- ET.tostring(tree, encoding="unicode", method="xml")
+ eTree.tostring(tree, encoding="unicode", method="xml")
).toprettyxml(indent=" ")
with open(os.path.join(resource_path, "%s.xml" % mode), "w") as f:
f.write(xmlstr)
@@ -202,26 +204,23 @@ def download_scripts(
CONFIG_FILE = config_path
if CONFIG_FILE != "":
- try:
- # Get config
- CONFPARSER.read(CONFIG_FILE)
- except:
- print("Can't read config file")
+ # Get config
+ CONFPARSER.read(CONFIG_FILE)
try:
username = CONFPARSER.get("jss", "username")
- except:
+ except configparser.NoOptionError:
print("Can't find username in configfile")
try:
password = CONFPARSER.get("jss", "password")
- except:
+ except configparser.NoOptionError:
print("Can't find password in configfile")
try:
url = CONFPARSER.get("jss", "server")
- except:
+ except configparser.NoOptionError:
print("Can't find url in configfile")
try:
export_path = CONFPARSER.get("jss", "export_path")
- except:
+ except configparser.NoOptionError:
print("Can't find export_path in config")
# Ask for password if not supplied via command line args