1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
#!/usr/bin/env python
"""Script to uninstall AWS CLI V2 Mac PKG"""
import argparse
import os
import re
import sys
from datetime import datetime
from subprocess import PIPE, CalledProcessError, check_output
SCRIPTS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(SCRIPTS_DIR)
from utils import BadRCError, run
_PKG_ID = 'com.amazon.aws.cli2'
_PKGUTIL_PATTERN = re.compile(
(
r'version:\s*(?P<version>.*?)\n'
r'volume:\s*(?P<volume>.*?)\n'
r'location:\s*(?P<location>.*?)\n'
r'install-time:\s*(?P<install_time>.*?)\n'
),
re.X,
)
def uninstall():
assert _is_installed(), 'Could not find AWS CLI installation.'
assert os.geteuid() == 0, 'Script must be run as root (with sudo).'
# First we remove all the files listed in the pkg's receipt file,
# and our own custom metadata file.
root_dir = _get_root_dir()
list_files = _get_file_list(root_dir)
_erase_files(list_files)
# Once these are all removed the directories should all be empty and can
# be deleted.
list_dirs = _get_dir_list(root_dir)
_erase_dirs(list_dirs)
# Finally we forget the package receipt.
_forget()
print('Successfully uninstalled AWS CLI from %s' % root_dir)
return 0
def _get_root_dir():
lines = run('pkgutil --pkg-info %s /' % _PKG_ID, echo=False)
output = _PKGUTIL_PATTERN.search(lines)
path = os.path.join(output.group('volume'), output.group('location'))
return path
def _get_file_list(root):
lines = run(
'pkgutil --only-files --files %s /' % _PKG_ID, echo=False
).split('\n')
pkg_file_list = [os.path.join(root, line) for line in lines if line]
extra_files = _read_install_metadata(root)
return pkg_file_list + extra_files
def _read_install_metadata(root):
# Install metadata is a list of files that were installed by helper scripts
# executed by the PKG. In the AWS CLI V2's case, we use a postinstall
# script to add binaries symlinks to /usr/bin. These are untracked by the
# pkg receipt. To track them we add them to a special .install-metdata file
# in the installer directory.
metadata_path = os.path.join(root, 'aws-cli', '.install-metadata')
if not os.path.isfile(metadata_path):
return []
extra_files = open(metadata_path).read()
return extra_files.split('\n')[:-1]
def _get_dir_list(root):
lines = run(
'pkgutil --only-dirs --files %s /' % _PKG_ID, echo=False
).split('\n')
# Longer directory names are listed first to force them to come before
# their parent directories. This ensures that child directories are
# deleted before their parents.
return sorted(
[os.path.join(root, line) for line in lines if line],
key=lambda x: -len(x),
)
def _erase_files(file_list):
for path in file_list:
if os.path.isfile(path) or os.path.islink(path):
os.remove(path)
def _erase_dirs(dir_list):
for path in dir_list:
if os.path.isdir(path):
os.rmdir(path)
def _forget():
# Forget is the pkgutil command to delete the pkg installer receipt.
# Once the files have been deleted, the pkgutil command will continue to
# report that they are installed until the pkg id has been forgotten.
run('pkgutil --forget %s' % _PKG_ID, echo=False)
def check():
assert _is_installed(), 'Could not find AWS CLI installation.'
lines = run('pkgutil --pkg-info %s /' % _PKG_ID, echo=False)
output = _PKGUTIL_PATTERN.search(lines)
root = os.path.join(output.group('volume'), output.group('location'))
print(
'Found AWS CLI version %s installed at %s'
% (output.group('version'), root)
)
print(
'Installed on %s'
% datetime.fromtimestamp(int(output.group('install_time')))
)
command = 'sudo %s uninstall' % os.path.abspath(__file__)
print('To uninstall run the command:')
print(command)
return 0
def _is_installed():
try:
result = run('pkgutil --pkg-info %s /' % _PKG_ID, echo=False)
except BadRCError:
return False
return True
def _warn_missing_arg(print_help):
# wrap `parser.print_help()` to return 1 so any callers don't receive
# a potentially misleading 0 exit code from a failed call.
def missing_arg_warning():
print(
'Missing input: script requires at least one positional argument\n'
)
print_help()
return 1
return missing_arg_warning
def main():
parser = argparse.ArgumentParser(usage=__doc__)
subparsers = parser.add_subparsers()
check_parser = subparsers.add_parser(
'check',
help=(
'Check if the AWS CLI is currently installed from a PKG '
'installer.'
),
)
check_parser.set_defaults(func=check)
uninstall_parser = subparsers.add_parser(
'uninstall', help='Uninstall the AWS CLI installed from the Mac PKG'
)
uninstall_parser.set_defaults(func=uninstall)
# default to help string if no args are passed
parser.set_defaults(func=_warn_missing_arg(parser.print_help))
args = parser.parse_args()
return args.func()
if __name__ == '__main__':
try:
sys.exit(main())
except AssertionError as e:
print(e)
sys.exit(1)
|