mirror of
https://github.com/munki/munki.git
synced 2026-01-19 13:40:34 -06:00
Merge branch 'master' into installer-copy_as
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.5.0</string>
|
||||
<string>3.5.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -425,7 +425,7 @@ def getRunningBlockingApps(appnames):
|
||||
if appname.endswith('.app'):
|
||||
# search by filename
|
||||
matching_items = [item for item in proc_list
|
||||
if '/'+ appname + '/' in item]
|
||||
if '/'+ appname + '/Contents/MacOS/' in item]
|
||||
else:
|
||||
# check executable name
|
||||
matching_items = [item for item in proc_list
|
||||
@@ -434,7 +434,7 @@ def getRunningBlockingApps(appnames):
|
||||
if not matching_items:
|
||||
# try adding '.app' to the name and check again
|
||||
matching_items = [item for item in proc_list
|
||||
if '/' + appname + '.app/' in item]
|
||||
if '/' + appname + '.app/Contents/MacOS/' in item]
|
||||
|
||||
matching_items = set(matching_items)
|
||||
for path in matching_items:
|
||||
|
||||
@@ -612,6 +612,14 @@ def main():
|
||||
itemhash = munkicommon.getsha256hash(item)
|
||||
|
||||
if item.endswith('.dmg'):
|
||||
if munkicommon.DMGisWritable(item):
|
||||
print >> sys.stderr, ("WARNING: %s is a writable disk "
|
||||
"image. Checksum verification is not supported."
|
||||
% item)
|
||||
print >> sys.stderr, ("WARNING: Consider converting "
|
||||
"%s to a read-only disk image."
|
||||
% item)
|
||||
itemhash = "N/A"
|
||||
catinfo = getCatalogInfoFromDmg(item, options)
|
||||
if (catinfo and
|
||||
catinfo.get('installer_type') == "AdobeCS5Installer"):
|
||||
@@ -668,7 +676,8 @@ def main():
|
||||
catinfo['version'] = options.pkgvers
|
||||
|
||||
catinfo['installer_item_size'] = int(itemsize/1024)
|
||||
catinfo['installer_item_hash'] = itemhash
|
||||
if itemhash != "N/A":
|
||||
catinfo['installer_item_hash'] = itemhash
|
||||
|
||||
# try to generate the correct item location
|
||||
temppath = item
|
||||
|
||||
@@ -596,7 +596,7 @@ def installWithInfo(
|
||||
|
||||
retcode = 0
|
||||
if 'preinstall_script' in item:
|
||||
retcode = runEmbeddedScript('preinstall_script', item)
|
||||
retcode = munkicommon.runEmbeddedScript('preinstall_script', item)
|
||||
|
||||
if retcode == 0 and 'installer_item' in item:
|
||||
display_name = item.get('display_name') or item.get('name')
|
||||
@@ -722,7 +722,8 @@ def installWithInfo(
|
||||
if retcode == 0 and 'postinstall_script' in item:
|
||||
# only run embedded postinstall script if the install did not
|
||||
# return a failure code
|
||||
retcode = runEmbeddedScript('postinstall_script', item)
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'postinstall_script', item)
|
||||
if retcode:
|
||||
# we won't consider postinstall script failures as fatal
|
||||
# since the item has been installed via package/disk image
|
||||
@@ -820,98 +821,6 @@ def installWithInfo(
|
||||
return (restartflag, skipped_installs)
|
||||
|
||||
|
||||
def writefile(stringdata, path):
|
||||
'''Writes string data to path.
|
||||
Returns the path on success, empty string on failure.'''
|
||||
try:
|
||||
fileobject = open(path, mode='w', buffering=1)
|
||||
print >> fileobject, stringdata.encode('UTF-8')
|
||||
fileobject.close()
|
||||
return path
|
||||
except (OSError, IOError):
|
||||
munkicommon.display_error("Couldn't write %s" % stringdata)
|
||||
return ""
|
||||
|
||||
|
||||
def runEmbeddedScript(scriptname, pkginfo_item):
|
||||
'''Runs a script embedded in the pkginfo.
|
||||
Returns the result code.'''
|
||||
|
||||
# get the script text from the pkginfo
|
||||
script_text = pkginfo_item.get(scriptname)
|
||||
itemname = pkginfo_item.get('name')
|
||||
if not script_text:
|
||||
munkicommon.display_error(
|
||||
'Missing script %s for %s' % (scriptname, itemname))
|
||||
return -1
|
||||
|
||||
# write the script to a temp file
|
||||
scriptpath = os.path.join(munkicommon.tmpdir, scriptname)
|
||||
if writefile(script_text, scriptpath):
|
||||
cmd = ['/bin/chmod', '-R', 'o+x', scriptpath]
|
||||
retcode = subprocess.call(cmd)
|
||||
if retcode:
|
||||
munkicommon.display_error(
|
||||
'Error setting script mode in %s for %s'
|
||||
% (scriptname, itemname))
|
||||
return -1
|
||||
else:
|
||||
munkicommon.display_error(
|
||||
'Cannot write script %s for %s' % (scriptname, itemname))
|
||||
return -1
|
||||
|
||||
# now run the script
|
||||
return runScript(itemname, scriptpath, scriptname)
|
||||
|
||||
|
||||
def runScript(itemname, path, scriptname):
|
||||
'''Runs a script, Returns return code.'''
|
||||
munkicommon.display_status_minor(
|
||||
'Running %s for %s ' % (scriptname, itemname))
|
||||
if munkicommon.munkistatusoutput:
|
||||
# set indeterminate progress bar
|
||||
munkistatus.percent(-1)
|
||||
|
||||
scriptoutput = []
|
||||
try:
|
||||
proc = subprocess.Popen(path, shell=False, bufsize=1,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
except OSError, e:
|
||||
munkicommon.display_error(
|
||||
'Error executing script %s: %s' % (scriptname, str(e)))
|
||||
return -1
|
||||
|
||||
while True:
|
||||
msg = proc.stdout.readline().decode('UTF-8')
|
||||
if not msg and (proc.poll() != None):
|
||||
break
|
||||
# save all script output in case there is
|
||||
# an error so we can dump it to the log
|
||||
scriptoutput.append(msg)
|
||||
msg = msg.rstrip("\n")
|
||||
munkicommon.display_info(msg)
|
||||
|
||||
retcode = proc.poll()
|
||||
if retcode:
|
||||
munkicommon.display_error(
|
||||
'Running %s for %s failed.' % (scriptname, itemname))
|
||||
munkicommon.display_error("-"*78)
|
||||
for line in scriptoutput:
|
||||
munkicommon.display_error("\t%s" % line.rstrip("\n"))
|
||||
munkicommon.display_error("-"*78)
|
||||
else:
|
||||
munkicommon.log(
|
||||
'Running %s for %s was successful.' % (scriptname, itemname))
|
||||
|
||||
if munkicommon.munkistatusoutput:
|
||||
# clear indeterminate progress bar
|
||||
munkistatus.percent(0)
|
||||
|
||||
return retcode
|
||||
|
||||
|
||||
def skippedItemsThatRequireThisItem(item, skipped_items):
|
||||
'''Looks for items in the skipped_items that require or are update_for
|
||||
the current item. Returns a list of matches.'''
|
||||
@@ -977,7 +886,7 @@ def processRemovals(removallist, only_unattended=False):
|
||||
retcode = 0
|
||||
# run preuninstall_script if it exists
|
||||
if 'preuninstall_script' in item:
|
||||
retcode = runEmbeddedScript('preuninstall_script', item)
|
||||
retcode = munkicommon.runEmbeddedScript('preuninstall_script', item)
|
||||
|
||||
if retcode == 0 and 'uninstall_method' in item:
|
||||
uninstallmethod = item['uninstall_method']
|
||||
@@ -1022,7 +931,8 @@ def processRemovals(removallist, only_unattended=False):
|
||||
name)
|
||||
|
||||
elif uninstallmethod == 'uninstall_script':
|
||||
retcode = runEmbeddedScript('uninstall_script', item)
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'uninstall_script', item)
|
||||
if (retcode == 0 and
|
||||
item.get('RestartAction') == "RequireRestart"):
|
||||
restartFlag = True
|
||||
@@ -1030,7 +940,7 @@ def processRemovals(removallist, only_unattended=False):
|
||||
elif os.path.exists(uninstallmethod) and \
|
||||
os.access(uninstallmethod, os.X_OK):
|
||||
# it's a script or program to uninstall
|
||||
retcode = runScript(
|
||||
retcode = munkicommon.runScript(
|
||||
name, uninstallmethod, 'uninstall script')
|
||||
if (retcode == 0 and
|
||||
item.get('RestartAction') == "RequireRestart"):
|
||||
@@ -1043,7 +953,8 @@ def processRemovals(removallist, only_unattended=False):
|
||||
retcode = -99
|
||||
|
||||
if retcode == 0 and item.get('postuninstall_script'):
|
||||
retcode = runEmbeddedScript('postuninstall_script', item)
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'postuninstall_script', item)
|
||||
if retcode:
|
||||
# we won't consider postuninstall script failures as fatal
|
||||
# since the item has been uninstalled
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Copyright 2009-2011 Greg Neagle.
|
||||
# Copyright 2009-2012 Greg Neagle.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -44,10 +44,12 @@ from types import StringType
|
||||
from xml.dom import minidom
|
||||
|
||||
from Foundation import NSArray, NSDate, NSMetadataQuery, NSPredicate, NSRunLoop
|
||||
from Foundation import CFPreferencesCopyAppValue
|
||||
from Foundation import CFPreferencesSetValue
|
||||
from Foundation import CFPreferencesAppSynchronize
|
||||
from Foundation import CFPreferencesCopyAppValue
|
||||
from Foundation import CFPreferencesCopyKeyList
|
||||
from Foundation import CFPreferencesSetValue
|
||||
from Foundation import kCFPreferencesAnyUser
|
||||
from Foundation import kCFPreferencesCurrentUser
|
||||
from Foundation import kCFPreferencesCurrentHost
|
||||
|
||||
import munkistatus
|
||||
@@ -469,7 +471,7 @@ def validateDateFormat(datetime_string):
|
||||
formatted_datetime_string = ''
|
||||
try:
|
||||
formatted_datetime_string = time.strftime(
|
||||
'%Y-%m-%dT%H:%M:%SZ', time.strptime(datetime_string,
|
||||
'%Y-%m-%dT%H:%M:%SZ', time.strptime(datetime_string,
|
||||
'%Y-%m-%dT%H:%M:%SZ'))
|
||||
except:
|
||||
pass
|
||||
@@ -547,7 +549,7 @@ def saveappdata():
|
||||
os.path.join(
|
||||
pref('ManagedInstallDir'), 'ApplicationInventory.plist'))
|
||||
except FoundationPlist.NSPropertyListSerializationException, err:
|
||||
munkicommon.display_warning(
|
||||
display_warning(
|
||||
'Unable to save inventory report: %s' % err)
|
||||
|
||||
|
||||
@@ -755,6 +757,27 @@ def getFirstPlist(textString):
|
||||
|
||||
# dmg helpers
|
||||
|
||||
def DMGisWritable(dmgpath):
|
||||
'''Attempts to determine if the given disk image is writable'''
|
||||
proc = subprocess.Popen(
|
||||
['/usr/bin/hdiutil', 'imageinfo', dmgpath, '-plist'],
|
||||
bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(out, err) = proc.communicate()
|
||||
if err:
|
||||
print >> sys.stderr, (
|
||||
'hdiutil error %s with image %s.' % (err, dmgpath))
|
||||
(pliststr, out) = getFirstPlist(out)
|
||||
if pliststr:
|
||||
try:
|
||||
plist = FoundationPlist.readPlistFromString(pliststr)
|
||||
format = plist.get('Format')
|
||||
if format in ['UDSB', 'UDSP', 'UDRW', 'RdWr']:
|
||||
return True
|
||||
except FoundationPlist.NSPropertyListSerializationException:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def DMGhasSLA(dmgpath):
|
||||
'''Returns true if dmg has a Software License Agreement.
|
||||
These dmgs normally cannot be attached without user intervention'''
|
||||
@@ -907,6 +930,65 @@ def isApplication(pathname):
|
||||
# managed installs preferences/metadata
|
||||
#####################################################
|
||||
|
||||
class Preferences(object):
|
||||
"""Class which directly reads/writes Apple CF preferences."""
|
||||
|
||||
def __init__(self, bundle_id, user=kCFPreferencesAnyUser):
|
||||
"""Init.
|
||||
|
||||
Args:
|
||||
bundle_id: str, like 'ManagedInstalls'
|
||||
"""
|
||||
if bundle_id.endswith('.plist'):
|
||||
bundle_id = bundle_id[:-6]
|
||||
self.bundle_id = bundle_id
|
||||
self.user = user
|
||||
|
||||
def __iter__(self):
|
||||
keys = CFPreferencesCopyKeyList(
|
||||
self.bundle_id, self.user, kCFPreferencesCurrentHost)
|
||||
if keys is not None:
|
||||
for i in keys:
|
||||
yield i
|
||||
|
||||
def __contains__(self, pref_name):
|
||||
pref_value = CFPreferencesCopyAppValue(pref_name, self.bundle_id)
|
||||
return pref_value is not None
|
||||
|
||||
def __getitem__(self, pref_name):
|
||||
return CFPreferencesCopyAppValue(pref_name, self.bundle_id)
|
||||
|
||||
def __setitem__(self, pref_name, pref_value):
|
||||
CFPreferencesSetValue(
|
||||
pref_name, pref_value, self.bundle_id, self.user,
|
||||
kCFPreferencesCurrentHost)
|
||||
CFPreferencesAppSynchronize(self.bundle_id)
|
||||
|
||||
def __delitem__(self, pref_name):
|
||||
self.__setitem__(pref_name, None)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %s>' % (self.__class__.__name__, self.bundle_id)
|
||||
|
||||
def get(self, pref_name, default=None):
|
||||
if not pref_name in self:
|
||||
return default
|
||||
else:
|
||||
return self.__getitem__(pref_name)
|
||||
|
||||
|
||||
class ManagedInstallsPreferences(Preferences):
|
||||
"""Preferences which read from /L/P/ManagedInstalls."""
|
||||
def __init__(self):
|
||||
Preferences.__init__(self, 'ManagedInstalls', kCFPreferencesAnyUser)
|
||||
|
||||
|
||||
class SecureManagedInstallsPreferences(Preferences):
|
||||
"""Preferences which read from /private/var/root/L/P/ManagedInstalls."""
|
||||
def __init__(self):
|
||||
Preferences.__init__(self, 'ManagedInstalls', kCFPreferencesCurrentUser)
|
||||
|
||||
|
||||
def reload_prefs():
|
||||
"""Uses CFPreferencesAppSynchronize(BUNDLE_ID)
|
||||
to make sure we have the latest prefs. Call this
|
||||
@@ -1530,10 +1612,10 @@ def getChoiceChangesXML(pkgitem):
|
||||
(out, unused_err) = proc.communicate()
|
||||
if out:
|
||||
plist = FoundationPlist.readPlistFromString(out)
|
||||
|
||||
|
||||
# list comprehension to populate choices with those items
|
||||
# whose 'choiceAttribute' value is 'selected'
|
||||
choices = [item for item in plist
|
||||
choices = [item for item in plist
|
||||
if 'selected' in item['choiceAttribute']]
|
||||
except:
|
||||
# No choices found or something went wrong
|
||||
@@ -2024,7 +2106,7 @@ def getConditions():
|
||||
which can be placed into /usr/local/munki/conditions"""
|
||||
global CONDITIONS
|
||||
if not CONDITIONS:
|
||||
# define path to conditions directory which would contain
|
||||
# define path to conditions directory which would contain
|
||||
# admin created scripts
|
||||
scriptdir = os.path.realpath(os.path.dirname(sys.argv[0]))
|
||||
conditionalscriptdir = os.path.join(scriptdir, "conditions")
|
||||
@@ -2058,13 +2140,13 @@ def getConditions():
|
||||
else:
|
||||
# /usr/local/munki/conditions does not exist
|
||||
pass
|
||||
if (os.path.exists(conditionalitemspath) and
|
||||
if (os.path.exists(conditionalitemspath) and
|
||||
validPlist(conditionalitemspath)):
|
||||
# import conditions into CONDITIONS dict
|
||||
CONDITIONS = FoundationPlist.readPlist(conditionalitemspath)
|
||||
os.unlink(conditionalitemspath)
|
||||
else:
|
||||
# either ConditionalItems.plist does not exist
|
||||
# either ConditionalItems.plist does not exist
|
||||
# or does not pass validation
|
||||
CONDITIONS = {}
|
||||
return CONDITIONS
|
||||
@@ -2079,7 +2161,7 @@ def isAppRunning(appname):
|
||||
if appname.endswith('.app'):
|
||||
# search by filename
|
||||
matching_items = [item for item in proc_list
|
||||
if '/'+ appname + '/' in item]
|
||||
if '/'+ appname + '/Contents/MacOS/' in item]
|
||||
else:
|
||||
# check executable name
|
||||
matching_items = [item for item in proc_list
|
||||
@@ -2087,7 +2169,7 @@ def isAppRunning(appname):
|
||||
if not matching_items:
|
||||
# try adding '.app' to the name and check again
|
||||
matching_items = [item for item in proc_list
|
||||
if '/'+ appname + '.app/' in item]
|
||||
if '/'+ appname + '.app/Contents/MacOS/' in item]
|
||||
|
||||
if matching_items:
|
||||
# it's running!
|
||||
@@ -2208,6 +2290,100 @@ def findProcesses(user=None, exe=None):
|
||||
return pids
|
||||
|
||||
|
||||
# utility functions for running scripts from pkginfo files
|
||||
# used by updatecheck.py and installer.py
|
||||
|
||||
def writefile(stringdata, path):
|
||||
'''Writes string data to path.
|
||||
Returns the path on success, empty string on failure.'''
|
||||
try:
|
||||
fileobject = open(path, mode='w', buffering=1)
|
||||
print >> fileobject, stringdata.encode('UTF-8')
|
||||
fileobject.close()
|
||||
return path
|
||||
except (OSError, IOError):
|
||||
display_error("Couldn't write %s" % stringdata)
|
||||
return ""
|
||||
|
||||
|
||||
def runEmbeddedScript(scriptname, pkginfo_item, suppress_error=False):
|
||||
'''Runs a script embedded in the pkginfo.
|
||||
Returns the result code.'''
|
||||
|
||||
# get the script text from the pkginfo
|
||||
script_text = pkginfo_item.get(scriptname)
|
||||
itemname = pkginfo_item.get('name')
|
||||
if not script_text:
|
||||
display_error(
|
||||
'Missing script %s for %s' % (scriptname, itemname))
|
||||
return -1
|
||||
|
||||
# write the script to a temp file
|
||||
scriptpath = os.path.join(tmpdir, scriptname)
|
||||
if writefile(script_text, scriptpath):
|
||||
cmd = ['/bin/chmod', '-R', 'o+x', scriptpath]
|
||||
retcode = subprocess.call(cmd)
|
||||
if retcode:
|
||||
display_error(
|
||||
'Error setting script mode in %s for %s'
|
||||
% (scriptname, itemname))
|
||||
return -1
|
||||
else:
|
||||
display_error(
|
||||
'Cannot write script %s for %s' % (scriptname, itemname))
|
||||
return -1
|
||||
|
||||
# now run the script
|
||||
return runScript(
|
||||
itemname, scriptpath, scriptname, suppress_error=suppress_error)
|
||||
|
||||
|
||||
def runScript(itemname, path, scriptname, suppress_error=False):
|
||||
'''Runs a script, Returns return code.'''
|
||||
display_status_minor(
|
||||
'Running %s for %s ' % (scriptname, itemname))
|
||||
if munkistatusoutput:
|
||||
# set indeterminate progress bar
|
||||
munkistatus.percent(-1)
|
||||
|
||||
scriptoutput = []
|
||||
try:
|
||||
proc = subprocess.Popen(path, shell=False, bufsize=1,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
except OSError, e:
|
||||
display_error(
|
||||
'Error executing script %s: %s' % (scriptname, str(e)))
|
||||
return -1
|
||||
|
||||
while True:
|
||||
msg = proc.stdout.readline().decode('UTF-8')
|
||||
if not msg and (proc.poll() != None):
|
||||
break
|
||||
# save all script output in case there is
|
||||
# an error so we can dump it to the log
|
||||
scriptoutput.append(msg)
|
||||
msg = msg.rstrip("\n")
|
||||
display_info(msg)
|
||||
|
||||
retcode = proc.poll()
|
||||
if retcode and not suppress_error:
|
||||
display_error(
|
||||
'Running %s for %s failed.' % (scriptname, itemname))
|
||||
display_error("-"*78)
|
||||
for line in scriptoutput:
|
||||
display_error("\t%s" % line.rstrip("\n"))
|
||||
display_error("-"*78)
|
||||
elif not suppress_error:
|
||||
log('Running %s for %s was successful.' % (scriptname, itemname))
|
||||
|
||||
if munkistatusoutput:
|
||||
# clear indeterminate progress bar
|
||||
munkistatus.percent(0)
|
||||
|
||||
return retcode
|
||||
|
||||
|
||||
def forceLogoutNow():
|
||||
"""Force the logout of interactive GUI users and spawn MSU."""
|
||||
|
||||
@@ -22,18 +22,12 @@ Created by Greg Neagle on 2008-11-13.
|
||||
"""
|
||||
|
||||
# standard libs
|
||||
#import calendar
|
||||
#import errno
|
||||
import datetime
|
||||
import os
|
||||
#import re
|
||||
#import shutil
|
||||
import subprocess
|
||||
import socket
|
||||
#import time
|
||||
import urllib2
|
||||
import urlparse
|
||||
#import xattr
|
||||
from OpenSSL.crypto import load_certificate, FILETYPE_PEM
|
||||
|
||||
# our libs
|
||||
@@ -328,12 +322,14 @@ def analyzeInstalledPkgs():
|
||||
if not name in references[pkgid]:
|
||||
references[pkgid].append(name)
|
||||
|
||||
#PKGDATA['itemname_to_pkgid'] = itemname_to_pkgid
|
||||
#PKGDATA['pkgid_to_itemname'] = pkgid_to_itemname
|
||||
PKGDATA['receipts_for_name'] = installedpkgsmatchedtoname
|
||||
PKGDATA['installed_names'] = installed
|
||||
#PKGDATA['partiallyinstalled_names'] = partiallyinstalled
|
||||
PKGDATA['pkg_references'] = references
|
||||
|
||||
# left here for future debugging/testing use....
|
||||
#PKGDATA['itemname_to_pkgid'] = itemname_to_pkgid
|
||||
#PKGDATA['pkgid_to_itemname'] = pkgid_to_itemname
|
||||
#PKGDATA['partiallyinstalled_names'] = partiallyinstalled
|
||||
#PKGDATA['orphans'] = orphans
|
||||
#PKGDATA['matched_orphans'] = matched_orphans
|
||||
#ManagedInstallDir = munkicommon.pref('ManagedInstallDir')
|
||||
@@ -656,6 +652,14 @@ def compareReceiptVersion(item):
|
||||
|
||||
Raises munkicommon.Error if there's an error in the input
|
||||
"""
|
||||
if item.get('optional'):
|
||||
# receipt has been marked as optional, so it doesn't matter
|
||||
# if it's installed or not. Return 1
|
||||
# only check receipts not marked as optional
|
||||
munkicommon.display_debug1(
|
||||
'Skipping %s because it is marked as optional'
|
||||
% item.get('packageid', item.get('name')))
|
||||
return 1
|
||||
if not INSTALLEDPKGS:
|
||||
getInstalledPackages()
|
||||
if 'packageid' in item and 'version' in item:
|
||||
@@ -1149,7 +1153,20 @@ def installedState(item_pl):
|
||||
Returns 0 otherwise.
|
||||
"""
|
||||
foundnewer = False
|
||||
|
||||
|
||||
if item_pl.get('installcheck_script'):
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'installcheck_script', item_pl, suppress_error=True)
|
||||
munkicommon.display_debug1(
|
||||
'installcheck_script returned %s' % retcode)
|
||||
# retcode 0 means install is needed
|
||||
if retcode == 0:
|
||||
return 0
|
||||
# non-zero could be an error or successfully indicating
|
||||
# that an install is not needed. We hope it's the latter.
|
||||
# return 1 so we're marked as not needing to be installed
|
||||
return 1
|
||||
|
||||
if item_pl.get('softwareupdatename'):
|
||||
availableAppleUpdates = appleupdates.softwareUpdateList()
|
||||
munkicommon.display_debug2(
|
||||
@@ -1166,8 +1183,8 @@ def installedState(item_pl):
|
||||
item_pl['softwareupdatename'])
|
||||
# return 1 so we're marked as not needing to be installed
|
||||
return 1
|
||||
|
||||
# does 'installs' exist and is it non-empty?
|
||||
|
||||
# does 'installs' exist and is it non-empty?
|
||||
if item_pl.get('installs', None):
|
||||
installitems = item_pl['installs']
|
||||
for item in installitems:
|
||||
@@ -1215,7 +1232,22 @@ def someVersionInstalled(item_pl):
|
||||
|
||||
Args:
|
||||
item_pl: item plist for the item to check for version of.
|
||||
|
||||
Returns a boolean.
|
||||
"""
|
||||
if item_pl.get('installcheck_script'):
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'installcheck_script', item_pl, suppress_error=True)
|
||||
munkicommon.display_debug1(
|
||||
'installcheck_script returned %s' % retcode)
|
||||
# retcode 0 means install is needed
|
||||
# (ie, item is not installed)
|
||||
if retcode == 0:
|
||||
return False
|
||||
# non-zero could be an error or successfully indicating
|
||||
# that an install is not needed. We hope it's the latter.
|
||||
return True
|
||||
|
||||
# does 'installs' exist and is it non-empty?
|
||||
if item_pl.get('installs'):
|
||||
installitems = item_pl['installs']
|
||||
@@ -1256,7 +1288,35 @@ def evidenceThisIsInstalled(item_pl):
|
||||
If any tests pass, the item might be installed.
|
||||
This is used when determining if we can remove the item, thus
|
||||
the attention given to the uninstall method.
|
||||
|
||||
Returns a boolean.
|
||||
"""
|
||||
if item_pl.get('uninstallcheck_script'):
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'uninstallcheck_script', item_pl, suppress_error=True)
|
||||
munkicommon.display_debug1(
|
||||
'uninstallcheck_script returned %s' % retcode)
|
||||
# retcode 0 means uninstall is needed
|
||||
# (ie, item is installed)
|
||||
if retcode == 0:
|
||||
return True
|
||||
# non-zero could be an error or successfully indicating
|
||||
# that an uninstall is not needed
|
||||
return False
|
||||
|
||||
if item_pl.get('installcheck_script'):
|
||||
retcode = munkicommon.runEmbeddedScript(
|
||||
'installcheck_script', item_pl, suppress_error=True)
|
||||
munkicommon.display_debug1(
|
||||
'installcheck_script returned %s' % retcode)
|
||||
# retcode 0 means install is needed
|
||||
# (ie, item is not installed)
|
||||
if retcode == 0:
|
||||
return False
|
||||
# non-zero could be an error or successfully indicating
|
||||
# that an install is not needed
|
||||
return True
|
||||
|
||||
foundallinstallitems = False
|
||||
if ('installs' in item_pl and
|
||||
item_pl.get('uninstall_method') != 'removepackages'):
|
||||
|
||||
Reference in New Issue
Block a user