You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.7 KiB
167 lines
5.7 KiB
#!/usr/bin/env python
|
|
# coding=utf-8
|
|
#
|
|
# Copyright © Splunk, Inc. All Rights Reserved.
|
|
|
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
|
|
from os import path
|
|
import json
|
|
import sys
|
|
|
|
from slim.utils import * # pylint: disable=redefined-builtin
|
|
from slim.app import *
|
|
from slim.command import * # pylint: disable=redefined-builtin
|
|
from slim.utils import SlimInstallationGraphActions
|
|
from slim.app._internal.object_view import ObjectView
|
|
|
|
|
|
# Argument parser definition
|
|
|
|
parser = SlimArgumentParser(
|
|
description='perform an update action on an installation graph',
|
|
epilog='''Update action can be add, set, update, remove
|
|
|
|
--actions add --package <path>
|
|
--actions set --package <path>
|
|
--actions update --package <path>
|
|
--actions remove --id <package app id>
|
|
|
|
Additional add and set parameters:
|
|
--combine-search-head-indexer-workloads <boolean>
|
|
--deployment-packages
|
|
--forwarder-workloads
|
|
''')
|
|
|
|
parser.add_argument_help()
|
|
parser.add_installation()
|
|
parser.add_output_directory(description='installation graph and deployment packages')
|
|
parser.add_repository()
|
|
parser.add_combine_search_head_indexer_workloads()
|
|
parser.add_forwarder_workloads()
|
|
parser.add_deployment_packages()
|
|
parser.add_target_os()
|
|
|
|
# Command-specific arguments
|
|
|
|
parser.add_argument(
|
|
'-a', '--action', required=True,
|
|
choices=SlimInstallationGraphActions,
|
|
help='apply action to the given installation graph: add, set, update or remove')
|
|
|
|
parser.add_argument(
|
|
'-p', '--package', type=string, default=None,
|
|
help='location of an app source package',
|
|
metavar='<app-source>')
|
|
|
|
# this option is intentionally undocumented, it shouldn't be used by the SLIM users
|
|
parser.add_argument(
|
|
'--is-external',
|
|
action='store_const', const=True, default=False)
|
|
|
|
parser.add_argument(
|
|
'--id', type=string, default=None,
|
|
help='package app id')
|
|
|
|
parser.add_argument(
|
|
'--disable-automatic-resolution',
|
|
action='store_const', const=True, default=False,
|
|
help='do not automatically resolve dependency conflicts by updating installed versions')
|
|
|
|
|
|
def main(args):
|
|
# translate args to action args
|
|
if args.action in [SlimInstallationGraphActions.add,
|
|
SlimInstallationGraphActions.set,
|
|
SlimInstallationGraphActions.update]:
|
|
actions_args = ObjectView((
|
|
('app_package', args.package),
|
|
('is_external', args.is_external),
|
|
('combine_search_head_indexer_workloads', args.combine_search_head_indexer_workloads),
|
|
('workloads', args.forwarder_workloads),
|
|
('deployment_packages', args.deployment_packages),
|
|
('target_os', args.target_os),
|
|
))
|
|
elif args.action == SlimInstallationGraphActions.remove:
|
|
if args.id is None:
|
|
raise SlimArgumentError('The remove action requires and app id, use the --id parameter to set this.')
|
|
actions_args = ObjectView((('app_id', args.id),))
|
|
else:
|
|
assert False # strange, this should never happen
|
|
|
|
# execute the action
|
|
server_collection = _update_installation(
|
|
args.installation,
|
|
args.repository,
|
|
[AppInstallationAction((('action', args.action), ('args', actions_args)))],
|
|
args.target_os,
|
|
args.disable_automatic_resolution
|
|
)
|
|
|
|
filename = path.join(args.output_dir, 'installation-update.json')
|
|
server_collection.save(filename)
|
|
SlimLogger.exit_on_error()
|
|
SlimLogger.information('Saved updated installation graph to ', encode_filename(filename))
|
|
|
|
|
|
def update_installation(installation_graph, action_list, target_os, disable_automatic_resolution=False):
|
|
|
|
if isinstance(installation_graph, dict):
|
|
installation_graph = json.dumps(installation_graph)
|
|
|
|
stream_type = SlimStringIOArgument(name="installation_graph.json")
|
|
|
|
with stream_type(value=installation_graph) as istream:
|
|
action_type = SlimInstallationActionArgument()
|
|
actions = []
|
|
for action in action_list:
|
|
action_item = action_type(value=json.dumps(action))
|
|
workloads = action.get('args', {}).get('workloads')
|
|
if workloads:
|
|
# "adjust" args.workloads making it compatible with _update_installation
|
|
# pylint: disable=no-member
|
|
action_item.args.workloads = AppDeploymentSpecification.from_forwarder_workloads(workloads)
|
|
# pylint: enable=no-member
|
|
actions.append(action_item)
|
|
|
|
server_collection = _update_installation(
|
|
istream, slim_configuration.repository_path, actions, target_os, disable_automatic_resolution
|
|
)
|
|
|
|
# Save the installation graph to the payload only (not file output)
|
|
server_collection.save(None)
|
|
SlimLogger.exit_on_error()
|
|
|
|
|
|
# pylint: disable=redefined-builtin
|
|
def _update_installation(file, repository, actions, target_os, disable_automatic_resolution):
|
|
|
|
SlimLogger.step('Updating installation graph at ', encode_filename(file.name))
|
|
|
|
server_collection = AppServerClassCollection.load(file, repository)
|
|
SlimLogger.exit_on_error()
|
|
|
|
# Disable installation graph update validation until all actions have been complete
|
|
server_collection.validate = False
|
|
|
|
for action in actions:
|
|
server_collection.update_installation(action, target_os, disable_automatic_resolution)
|
|
SlimLogger.exit_on_error()
|
|
|
|
# Enable installation graph validation again, and trigger a reload
|
|
server_collection.validate = True
|
|
server_collection.reload()
|
|
SlimLogger.exit_on_error()
|
|
|
|
return server_collection
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# noinspection PyBroadException
|
|
try:
|
|
main(parser.parse_args(sys.argv[1:]))
|
|
except SystemExit:
|
|
raise
|
|
except:
|
|
SlimLogger.fatal(exception_info=sys.exc_info())
|