示例#1
0
def main(kwargs: argparse.Namespace) -> int:
    """
	Runs the commandline specified by ``kwargs``.

	:param kwargs: An object that provides the attribute namespace representing this script's
		options. See ``genConfigRoutes.py --help`` for more information.
	:returns: an exit code for the program
	:raises KeyError: when ``kwargs`` does not faithfully represent a valid command line
	"""
    global LOG_FMT

    if kwargs.quiet:
        level = logging.CRITICAL + 1
    else:
        level = logging.getLevelName(kwargs.log_level)

    try:
        logging.basicConfig(level=level, format=LOG_FMT)
        logging.getLogger().setLevel(level)
    except ValueError:
        print("Unrecognized log level:", kwargs.log_level, file=sys.stderr)
        return 1

    try:
        instanceA, instanceB, loginA, loginB = consolidateVariables(kwargs)
    except ValueError as e:
        logging.debug("%s", e, exc_info=True, stack_info=True)
        logging.critical("(hint: try '-h'/'--help')")
        return 1

    verify = not kwargs.insecure

    # Instantiate connections and login
    with TOSession(host_ip=instanceA["host"], host_port=instanceA["port"], verify_cert=verify) as A,\
    TOSession(host_ip=instanceB["host"], host_port=instanceB["port"], verify_cert=verify) as B:

        try:
            A.login(loginA[0], loginA[1])
            B.login(loginB[0], loginB[1])
        except (OSError, LoginError) as e:
            logging.debug("%s", e, exc_info=True, stack_info=True)
            logging.critical("Failed to connect to Traffic Ops")
            return 2
        except (OperationError, InvalidJSONError) as e:
            logging.debug("%s", e, exc_info=True, stack_info=True)
            logging.critical("Failed to log in to Traffic Ops")
            logging.error(
                "Error was '%s' - are you sure your URLs and credentials are correct?",
                e)
            return 2
        for route in genRoutes(A, B, kwargs.snapshot,
                               kwargs.no_server_configs):
            print(route)

    return 0
示例#2
0
	def generate_inventory_list(self, target_to):
		"""Generate the inventory list for the specified TrafficOps instance"""
		with TOSession(self.to_url, verify_cert=self.verify_cert) as traffic_ops_api:
			traffic_ops_api.login(self.to_user, self.to_pass)
			servers = traffic_ops_api.get_servers()[0]
			out = {}
			out['_meta'] = {}
			out['_meta']['hostvars'] = {}
			out[target_to] = {}
			out[target_to]['hosts'] = []
			out["ungrouped"] = {}
			out['ungrouped']['hosts'] = []
			out['cachegroup'] = {}
			out['cachegroup']['children'] = []
			out['server_type'] = {}
			out['server_type']['children'] = []
			out['server_cdnName'] = {}
			out['server_cdnName']['children'] = []
			out['server_profile'] = {}
			out['server_profile']['children'] = []
			out['server_status'] = {}
			out['server_status']['children'] = []
			for server in servers:
				fqdn = server['hostName'] + '.' + server['domainName']
				out["ungrouped"]['hosts'].append(fqdn)
				out[target_to]['hosts'].append(fqdn)
				out['_meta']['hostvars'][fqdn] = {}
				out['_meta']['hostvars'][fqdn]['server_toFQDN'] = target_to
				out['_meta']['hostvars'][fqdn]['server_cachegroup'] = server['cachegroup']
				out['_meta']['hostvars'][fqdn]['server_cdnName'] = server['cdnName']
				out['_meta']['hostvars'][fqdn]['server_id'] = server['id']
				out['_meta']['hostvars'][fqdn]['server_ipAddress'] = server['ipAddress']
				out['_meta']['hostvars'][fqdn]['server_ip6Address'] = server['ip6Address']
				out['_meta']['hostvars'][fqdn]['server_offlineReason'] = server['offlineReason']
				out['_meta']['hostvars'][fqdn]['server_physLocation'] = server['physLocation']
				out['_meta']['hostvars'][fqdn]['server_profile'] = server['profile']
				out['_meta']['hostvars'][fqdn]['server_profileDesc'] = server['profileDesc']
				out['_meta']['hostvars'][fqdn]['server_status'] = server['status']
				out['_meta']['hostvars'][fqdn]['server_type'] = server['type']
				flat_server_profile = "server_profile|" + server['profile']
				flat_cachegroup = "cachegroup|" + server['cachegroup']
				flat_server_type = "server_type|" + server['type']
				flat_server_cdn_name = "server_cdnName|" + server['cdnName']
				flat_server_status = "server_status|" + server['status']
				if flat_server_profile not in out:
					out['server_profile']['children'].append(
						flat_server_profile)
					out[flat_server_profile] = self.populate_server_profile_vars(
						traffic_ops_api, server['profileId'])
				out[flat_server_profile]['hosts'].append(fqdn)
				if flat_cachegroup not in out:
					out['cachegroup']['children'].append(flat_cachegroup)
					cgdata = self.populate_cachegroups(
						traffic_ops_api,
						server['cachegroupId'])
					out[flat_cachegroup] = cgdata.cgvars
					flat_parent_cg = cgdata.primary_parent_group_name
					flat_second_parent_cg = cgdata.secondary_parent_group_name
					if flat_parent_cg not in out:
						out[flat_parent_cg] = {}
						out[flat_parent_cg]['children'] = []
					if flat_second_parent_cg not in out:
						out[flat_second_parent_cg] = {}
						out[flat_second_parent_cg]['children'] = []
					out[flat_parent_cg]['children'].append(flat_cachegroup)
					out[flat_second_parent_cg]['children'].append(
						flat_cachegroup)
				out[flat_cachegroup]['hosts'].append(fqdn)
				if flat_server_type not in out:
					out['server_type']['children'].append(flat_server_type)
					out[flat_server_type] = {}
					out[flat_server_type]['hosts'] = []
				out[flat_server_type]['hosts'].append(fqdn)
				if flat_server_cdn_name not in out:
					out['server_cdnName']['children'].append(
						flat_server_cdn_name)
					out[flat_server_cdn_name] = {}
					out[flat_server_cdn_name]['hosts'] = []
				out[flat_server_cdn_name]['hosts'].append(fqdn)
				if flat_server_status not in out:
					out['server_status']['children'].append(flat_server_status)
					out[flat_server_status] = {}
					out[flat_server_status]['hosts'] = []
				out[flat_server_status]['hosts'].append(fqdn)
		return out
示例#3
0
def parse_arguments(program):
    """
	A common-use function that parses the command line arguments.

	:param program: The name of the program being run - used for usage informational output
	:returns: The Traffic Ops HTTP session object, the requested path, any data to be sent, an output
	          format specification, whether or not the path is raw, and whether or not output should
	          be prettified
	"""
    from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
    parser = ArgumentParser(
        prog=program,
        formatter_class=ArgumentDefaultsHelpFormatter,
        description="A helper program for interfacing with the Traffic Ops API",
        epilog=(
            "Typically, one will want to connect and authenticate by defining "
            "the 'TO_URL', 'TO_USER' and 'TO_PASSWORD' environment variables "
            "rather than (respectively) the '--to-url', '--to-user' and "
            "'--to-password' command-line flags. Those flags are only "
            "required when said environment variables are not defined.\n"
            "%(prog)s will exit with a success provided a response was "
            "received and the status code of said response was less than 400. "
            "The exit code will be 1 if command line arguments cannot be "
            "parsed or authentication with the Traffic Ops server fails. "
            "In the event of some unknown error occurring when waiting for a "
            "response, the exit code will be 2. If the server responds with "
            "a status code indicating a client or server error, that status "
            "code will be used as the exit code."))

    parser.add_argument(
        "--to-url",
        type=str,
        help=
        ("The fully qualified domain name of the Traffic Ops server. Overrides "
         "'$TO_URL'. The format for both the environment variable and the flag "
         "is '[scheme]hostname[:port]'. That is, ports should be specified here, "
         "and they need not start with 'http://' or 'https://'. HTTPS is the "
         "assumed protocol unless the scheme _is_ provided and is 'http://'."))
    parser.add_argument(
        "--to-user",
        type=str,
        help=
        "The username to use when connecting to Traffic Ops. Overrides '$TO_USER"
    )
    parser.add_argument(
        "--to-password",
        type=str,
        help=
        "The password to use when authenticating to Traffic Ops. Overrides '$TO_PASSWORD'"
    )
    parser.add_argument("-k",
                        "--insecure",
                        action="store_true",
                        help="Do not verify SSL certificates")
    parser.add_argument(
        "-f",
        "--full",
        action="store_true",
        help=
        ("Also output HTTP request/response lines and headers, and request payload. "
         "This is equivalent to using '--request-headers', '--response-headers' "
         "and '--request-payload' at the same time."))
    parser.add_argument("--request-headers",
                        action="store_true",
                        help="Output request method line and headers")
    parser.add_argument("--response-headers",
                        action="store_true",
                        help="Output response status line and headers")
    parser.add_argument(
        "--request-payload",
        action="store_true",
        help=
        "Output request payload (will try to pretty-print if '--pretty' is given)"
    )
    parser.add_argument(
        "-r",
        "--raw-path",
        action="store_true",
        help=
        "Request exactly PATH; it won't be prefaced with '/api/{{api-version}}/"
    )
    parser.add_argument("-a",
                        "--api-version",
                        type=float,
                        default=2.0,
                        help="Specify the API version to request against")
    parser.add_argument(
        "-p",
        "--pretty",
        action="store_true",
        help=
        ("Pretty-print payloads as JSON. "
         "Note that this will make Content-Type headers \"wrong\", in general"
         ))
    parser.add_argument("-v",
                        "--version",
                        action="version",
                        help="Print version information and exit",
                        version="%(prog)s v" + __version__)
    parser.add_argument(
        "PATH",
        help="The path to the resource being requested - omit '/api/2.x'")
    parser.add_argument(
        "DATA",
        help=("An optional data string to pass with the request. If this is a "
              "filename, the contents of the file will be sent instead."),
        nargs='?')

    args = parser.parse_args()

    try:
        to_host = args.to_url if args.to_url else os.environ["TO_URL"]
    except KeyError as e:
        raise KeyError("Traffic Ops hostname not set! Set the TO_URL environment variable or use "\
                       "'--to-url'.") from e

    original_to_host = to_host
    to_host = urlparse(to_host, scheme="https")
    useSSL = to_host.scheme.lower() == "https"
    to_port = to_host.port
    if to_port is None:
        if useSSL:
            to_port = 443
        else:
            to_port = 80

    to_host = to_host.hostname
    if not to_host:
        raise KeyError(
            f"Invalid URL/host for Traffic Ops: '{original_to_host}'")

    s = TOSession(to_host,
                  host_port=to_port,
                  ssl=useSSL,
                  api_version=f"{args.api_version:.1f}",
                  verify_cert=not args.insecure)

    data = args.DATA
    if data and os.path.isfile(data):
        with open(data) as f:
            data = f.read()

    if isinstance(data, str):
        data = data.encode()

    try:
        to_user = args.to_user if args.to_user else os.environ["TO_USER"]
    except KeyError as e:
        raise KeyError("Traffic Ops user not set! Set the TO_USER environment variable or use "\
                       "'--to-user'.") from e

    try:
        to_passwd = args.to_password if args.to_password else os.environ[
            "TO_PASSWORD"]
    except KeyError as e:
        raise KeyError("Traffic Ops password not set! Set the TO_PASSWORD environment variable or "\
                       "use '--to-password'") from e

    try:
        s.login(to_user, to_passwd)
    except (OperationError, InvalidJSONError, LoginError) as e:
        raise PermissionError from e

    return (s, args.PATH, data, (args.request_headers
                                 or args.full, args.response_headers
                                 or args.full, args.request_payload
                                 or args.full), args.raw_path, args.pretty)
示例#4
0
def main(kwargs: argparse.Namespace) -> int:
    """
	Runs the commandline specified by ``kwargs``.

	:param kwargs: An object that provides the attribute namespace representing this script's
		options. See ``genConfigRoutes.py --help`` for more information.
	:returns: an exit code for the program
	:raises KeyError: when ``kwargs`` does not faithfully represent a valid command line
	"""
    global LOG_FMT

    if kwargs.quiet:
        level = logging.CRITICAL + 1
    else:
        level = logging.getLevelName(kwargs.log_level)

    try:
        logging.basicConfig(level=level, format=LOG_FMT)
        logging.getLogger().setLevel(level)
    except ValueError:
        print("Unrecognized log level:", kwargs.log_level, file=sys.stderr)
        return 1

    instanceA = kwargs.InstanceA
    instanceB = kwargs.InstanceB

    try:
        loginA = kwargs.LoginA.split(':')
        loginA = (loginA[0], ':'.join(loginA[1:]))
    except (KeyError, IndexError) as e:
        logging.critical(
            "Bad username/password pair: '%s' (hint: try -h/--help)",
            kwargs.LoginA)
        return 1

    loginB = loginA

    try:
        if kwargs.LoginB:
            loginB = kwargs.LoginB.split(':')
            loginB = (loginB[0], ':'.join(loginB[1:]))
            loginB = (loginB[0] if loginB[0] else loginA[0],
                      loginB[1] if loginB[1] else loginA[1])
    except (KeyError, IndexError) as e:
        logging.critical(
            "Bad username/password pair: '%s' (hint: try -h/--help)",
            kwargs.LoginB)
        return 1

    verify = not kwargs.insecure

    # Peel off all schemas
    if instanceA.startswith("https://"):
        instanceA = instanceA[8:]
    elif instanceA.startswith("http://"):
        instanceA = instanceA[7:]

    if instanceB.startswith("https://"):
        instanceB = instanceB[8:]
    elif instanceB.startswith("http://"):
        instanceB = instanceB[7:]

    # Parse out port numbers, if specified
    try:
        if ':' in instanceA:
            instanceA = instanceA.split(':')
            if len(instanceA) != 2:
                logging.critical("'%s' is not a valid Traffic Ops URL!",
                                 kwargs.InstanceA)
                return 1
            instanceA = {"host": instanceA[0], "port": int(instanceA[1])}
        else:
            instanceA = {"host": instanceA, "port": 443}
    except TypeError as e:
        logging.critical("'%s' is not a valid port number!", instanceA[1])
        logging.debug("%s", e, exc_info=True, stack_info=True)
        return 1

    try:
        if ':' in instanceB:
            instanceB = instanceB.split(':')
            if len(instanceB) != 2:
                logging.critical("'%s' is not a valid Traffic Ops URL!",
                                 kwargs.InstanceB)
            instanceB = {"host": instanceB[0], "port": int(instanceB[1])}
        else:
            instanceB = {"host": instanceB, "port": 443}
    except TypeError as e:
        logging.critical("'%s' is not a valid port number!", instanceB[1])
        logging.debug("%s", e, exc_info=True, stack_info=True)
        return 1

    # Instantiate connections and login
    with TOSession(host_ip=instanceA["host"], host_port=instanceA["port"], verify_cert=verify) as A,\
    TOSession(host_ip=instanceB["host"], host_port=instanceB["port"], verify_cert=verify) as B:

        try:
            A.login(loginA[0], loginA[1])
            B.login(loginB[0], loginB[1])
        except OSError as e:
            logging.debug("%s", e, exc_info=True, stack_info=True)
            logging.critical("Failed to connect to Traffic Ops")
            return 2
        except (OperationError, LoginError) as e:
            logging.debug("%s", e, exc_info=True, stack_info=True)
            logging.critical("Failed to log in to Traffic Ops")
            logging.error(
                "Error was '%s' - are you sure your URLs and credentials are correct?",
                e)
        for route in genRoutes(A, B):
            print(route)

    return 0