composer-cli: Add support for upload command
This allows the user to start an upload, get info about a specific upload, and to cancel, reset, or delete an upload.
This commit is contained in:
		
							parent
							
								
									27a4165089
								
							
						
					
					
						commit
						a414988ee8
					
				| @ -167,6 +167,7 @@ Summary: A command line tool for use with the lorax-composer API server | ||||
| 
 | ||||
| # From Distribution | ||||
| Requires: python3-urllib3 | ||||
| Requires: python3-toml | ||||
| 
 | ||||
| %description -n composer-cli | ||||
| A command line tool for use with the lorax-composer API server. Examine blueprints, | ||||
|  | ||||
| @ -25,14 +25,16 @@ from composer.cli.projects import projects_cmd | ||||
| from composer.cli.compose import compose_cmd | ||||
| from composer.cli.sources import sources_cmd | ||||
| from composer.cli.status import status_cmd | ||||
| from composer.cli.upload import upload_cmd | ||||
| 
 | ||||
| command_map = { | ||||
|     "blueprints": blueprints_cmd, | ||||
|     "modules": modules_cmd, | ||||
|     "projects": projects_cmd, | ||||
|     "compose": compose_cmd, | ||||
|     "sources": sources_cmd, | ||||
|     "status": status_cmd | ||||
|     "modules":    modules_cmd, | ||||
|     "projects":   projects_cmd, | ||||
|     "compose":    compose_cmd, | ||||
|     "sources":    sources_cmd, | ||||
|     "status":     status_cmd, | ||||
|     "upload":     upload_cmd | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -37,7 +37,7 @@ def composer_cli_parser(): | ||||
|                         help="Path to the socket file to listen on") | ||||
|     parser.add_argument("--log", dest="logfile", default=None, metavar="LOG", | ||||
|                         help="Path to logfile (./composer-cli.log)") | ||||
|     parser.add_argument("-a", "--api", dest="api_version", default="0", metavar="APIVER", | ||||
|     parser.add_argument("-a", "--api", dest="api_version", default="1", metavar="APIVER", | ||||
|                         help="API Version to use") | ||||
|     parser.add_argument("--test", dest="testmode", default=0, type=int, metavar="TESTMODE", | ||||
|                         help="Pass test mode to compose. 1=Mock compose with fail. 2=Mock compose with finished.") | ||||
|  | ||||
| @ -133,4 +133,24 @@ status_help = """ | ||||
| status show                         Show API server status. | ||||
| """ | ||||
| 
 | ||||
| epilog = compose_help + blueprints_help + modules_help + projects_help + sources_help + status_help | ||||
| upload_help = """ | ||||
| upload info <UPLOAD-UUID> | ||||
|     Details about an upload | ||||
| 
 | ||||
| upload start <BUILD-UUID> <PROVIDER> <PROFILE>|<PROFILE.TOML> | ||||
|     Upload a build image to the selected provider. | ||||
| 
 | ||||
| upload log <UPLOAD-UUID> | ||||
|     Show the upload log | ||||
| 
 | ||||
| upload cancel <UPLOAD-UUID> | ||||
|     Cancel an upload with that is queued or in progress | ||||
| 
 | ||||
| upload delete <UPLOAD-UUID> | ||||
|     Delete the upload and remove it from the build | ||||
| 
 | ||||
| upload reset <UPLOAD-UUID> | ||||
|     Reset the upload so that it can be tried again | ||||
| """ | ||||
| 
 | ||||
| epilog = compose_help + blueprints_help + modules_help + projects_help + sources_help + status_help + upload_help | ||||
|  | ||||
							
								
								
									
										241
									
								
								src/composer/cli/upload.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								src/composer/cli/upload.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,241 @@ | ||||
| # | ||||
| # Copyright (C) 2019  Red Hat, Inc. | ||||
| # | ||||
| # This program is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 2 of the License, or | ||||
| # (at your option) any later version. | ||||
| # | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| import logging | ||||
| log = logging.getLogger("composer-cli") | ||||
| 
 | ||||
| import json | ||||
| import toml | ||||
| import os | ||||
| 
 | ||||
| from composer import http_client as client | ||||
| from composer.cli.help import upload_help | ||||
| from composer.cli.utilities import handle_api_result | ||||
| 
 | ||||
| def upload_cmd(opts): | ||||
|     """Process upload commands | ||||
| 
 | ||||
|     :param opts: Cmdline arguments | ||||
|     :type opts: argparse.Namespace | ||||
|     :returns: Value to return from sys.exit() | ||||
|     :rtype: int | ||||
| 
 | ||||
|     This dispatches the upload commands to a function | ||||
|     """ | ||||
|     cmd_map = { | ||||
|         "info":   upload_info, | ||||
|         "start":  upload_start, | ||||
|         "log":    upload_log, | ||||
|         "cancel": upload_cancel, | ||||
|         "delete": upload_delete, | ||||
|         "reset":  upload_reset, | ||||
|         } | ||||
|     if opts.args[1] == "help" or opts.args[1] == "--help": | ||||
|         print(upload_help) | ||||
|         return 0 | ||||
|     elif opts.args[1] not in cmd_map: | ||||
|         log.error("Unknown upload command: %s", opts.args[1]) | ||||
|         return 1 | ||||
| 
 | ||||
|     return cmd_map[opts.args[1]](opts.socket, opts.api_version, opts.args[2:], opts.json, opts.testmode) | ||||
| 
 | ||||
| def upload_info(socket_path, api_version, args, show_json=False, testmode=0): | ||||
|     """Return detailed information about the upload | ||||
| 
 | ||||
|     :param socket_path: Path to the Unix socket to use for API communication | ||||
|     :type socket_path: str | ||||
|     :param api_version: Version of the API to talk to. eg. "0" | ||||
|     :type api_version: str | ||||
|     :param args: List of remaining arguments from the cmdline | ||||
|     :type args: list of str | ||||
|     :param show_json: Set to True to show the JSON output instead of the human readable output | ||||
|     :type show_json: bool | ||||
|     :param testmode: unused in this function | ||||
|     :type testmode: int | ||||
| 
 | ||||
|     upload info <uuid> | ||||
| 
 | ||||
|     This returns information about the upload, including uuid, name, status, service, and image. | ||||
|     """ | ||||
|     if len(args) == 0: | ||||
|         log.error("info is missing the upload uuid") | ||||
|         return 1 | ||||
| 
 | ||||
|     api_route = client.api_url(api_version, "/upload/info/%s" % args[0]) | ||||
|     result = client.get_url_json(socket_path, api_route) | ||||
|     (rc, exit_now) = handle_api_result(result, show_json) | ||||
|     if exit_now: | ||||
|         return rc | ||||
| 
 | ||||
|     image_path = result["upload"]["image_path"] | ||||
|     print("%s %-8s %-15s %-8s %s" % (result["upload"]["uuid"], | ||||
|                                      result["upload"]["status"], | ||||
|                                      result["upload"]["image_name"], | ||||
|                                      result["upload"]["provider_name"], | ||||
|                                      os.path.basename(image_path) if image_path else "UNFINISHED")) | ||||
| 
 | ||||
|     return rc | ||||
| 
 | ||||
| def upload_start(socket_path, api_version, args, show_json=False, testmode=0): | ||||
|     """Start upload up a build uuid image | ||||
| 
 | ||||
|     :param socket_path: Path to the Unix socket to use for API communication | ||||
|     :type socket_path: str | ||||
|     :param api_version: Version of the API to talk to. eg. "0" | ||||
|     :type api_version: str | ||||
|     :param args: List of remaining arguments from the cmdline | ||||
|     :type args: list of str | ||||
|     :param show_json: Set to True to show the JSON output instead of the human readable output | ||||
|     :type show_json: bool | ||||
|     :param testmode: unused in this function | ||||
|     :type testmode: int | ||||
| 
 | ||||
|     upload start <build-uuid> <image-name> [<provider> <profile> | <profile.toml>] | ||||
|     """ | ||||
|     if len(args) == 0: | ||||
|         log.error("start is missing the compose build id") | ||||
|         return 1 | ||||
|     if len(args) == 1: | ||||
|         log.error("start is missing the image name") | ||||
|         return 1 | ||||
|     if len(args) == 2: | ||||
|         log.error("start is missing the provider and profile details") | ||||
|         return 1 | ||||
| 
 | ||||
|     body = {"image_name": args[1]} | ||||
|     if len(args) == 3: | ||||
|         try: | ||||
|             body.update(toml.load(args[2])) | ||||
|         except toml.TomlDecodeError as e: | ||||
|             log.error(str(e)) | ||||
|             return 1 | ||||
|     elif len(args) == 4: | ||||
|         body["provider"] = args[2] | ||||
|         body["profile"] = args[3] | ||||
|     else: | ||||
|         log.error("start has incorrect number of arguments") | ||||
|         return 1 | ||||
| 
 | ||||
|     api_route = client.api_url(api_version, "/compose/uploads/schedule/%s" % args[0]) | ||||
|     result = client.post_url_json(socket_path, api_route, json.dumps(body)) | ||||
|     (rc, exit_now) = handle_api_result(result, show_json) | ||||
|     if exit_now: | ||||
|         return rc | ||||
| 
 | ||||
|     print("Upload %s added to the queue" % result["upload_id"]) | ||||
|     return rc | ||||
| 
 | ||||
| def upload_log(socket_path, api_version, args, show_json=False, testmode=0): | ||||
|     """Return the upload log | ||||
| 
 | ||||
|     :param socket_path: Path to the Unix socket to use for API communication | ||||
|     :type socket_path: str | ||||
|     :param api_version: Version of the API to talk to. eg. "0" | ||||
|     :type api_version: str | ||||
|     :param args: List of remaining arguments from the cmdline | ||||
|     :type args: list of str | ||||
|     :param show_json: Set to True to show the JSON output instead of the human readable output | ||||
|     :type show_json: bool | ||||
|     :param testmode: unused in this function | ||||
|     :type testmode: int | ||||
| 
 | ||||
|     upload log <build-uuid> | ||||
|     """ | ||||
|     if len(args) == 0: | ||||
|         log.error("log is missing the upload uuid") | ||||
|         return 1 | ||||
| 
 | ||||
|     api_route = client.api_url(api_version, "/upload/log/%s" % args[0]) | ||||
|     try: | ||||
|         result = client.get_url_raw(socket_path, api_route) | ||||
|     except RuntimeError as e: | ||||
|         print(str(e)) | ||||
|         return 1 | ||||
| 
 | ||||
|     print(result) | ||||
|     return 0 | ||||
| 
 | ||||
| def upload_cancel(socket_path, api_version, args, show_json=False, testmode=0): | ||||
|     """Cancel the queued or running upload | ||||
| 
 | ||||
|     :param socket_path: Path to the Unix socket to use for API communication | ||||
|     :type socket_path: str | ||||
|     :param api_version: Version of the API to talk to. eg. "0" | ||||
|     :type api_version: str | ||||
|     :param args: List of remaining arguments from the cmdline | ||||
|     :type args: list of str | ||||
|     :param show_json: Set to True to show the JSON output instead of the human readable output | ||||
|     :type show_json: bool | ||||
|     :param testmode: unused in this function | ||||
|     :type testmode: int | ||||
| 
 | ||||
|     upload cancel <build-uuid> | ||||
|     """ | ||||
|     if len(args) == 0: | ||||
|         log.error("cancel is missing the upload uuid") | ||||
|         return 1 | ||||
| 
 | ||||
|     api_route = client.api_url(api_version, "/upload/cancel/%s" % args[0]) | ||||
|     result = client.delete_url_json(socket_path, api_route) | ||||
|     return handle_api_result(result, show_json)[0] | ||||
| 
 | ||||
| def upload_delete(socket_path, api_version, args, show_json=False, testmode=0): | ||||
|     """Delete an upload and remove it from the build | ||||
| 
 | ||||
|     :param socket_path: Path to the Unix socket to use for API communication | ||||
|     :type socket_path: str | ||||
|     :param api_version: Version of the API to talk to. eg. "0" | ||||
|     :type api_version: str | ||||
|     :param args: List of remaining arguments from the cmdline | ||||
|     :type args: list of str | ||||
|     :param show_json: Set to True to show the JSON output instead of the human readable output | ||||
|     :type show_json: bool | ||||
|     :param testmode: unused in this function | ||||
|     :type testmode: int | ||||
| 
 | ||||
|     upload delete <build-uuid> | ||||
|     """ | ||||
|     if len(args) == 0: | ||||
|         log.error("delete is missing the upload uuid") | ||||
|         return 1 | ||||
| 
 | ||||
|     api_route = client.api_url(api_version, "/upload/delete/%s" % args[0]) | ||||
|     result = client.delete_url_json(socket_path, api_route) | ||||
|     return handle_api_result(result, show_json)[0] | ||||
| 
 | ||||
| def upload_reset(socket_path, api_version, args, show_json=False, testmode=0): | ||||
|     """Reset the upload and execute it again | ||||
| 
 | ||||
|     :param socket_path: Path to the Unix socket to use for API communication | ||||
|     :type socket_path: str | ||||
|     :param api_version: Version of the API to talk to. eg. "0" | ||||
|     :type api_version: str | ||||
|     :param args: List of remaining arguments from the cmdline | ||||
|     :type args: list of str | ||||
|     :param show_json: Set to True to show the JSON output instead of the human readable output | ||||
|     :type show_json: bool | ||||
|     :param testmode: unused in this function | ||||
|     :type testmode: int | ||||
| 
 | ||||
|     upload reset <build-uuid> | ||||
|     """ | ||||
|     if len(args) == 0: | ||||
|         log.error("reset is missing the upload uuid") | ||||
|         return 1 | ||||
| 
 | ||||
|     api_route = client.api_url(api_version, "/upload/reset/%s" % args[0]) | ||||
|     result = client.post_url_json(socket_path, api_route, json.dumps({})) | ||||
|     return handle_api_result(result, show_json)[0] | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user