You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by mi...@apache.org on 2019/02/11 16:57:38 UTC

[trafficcontrol] branch master updated: Ort.py environment variables (#3313)

This is an automated email from the ASF dual-hosted git repository.

mitchell852 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 2d6106b  Ort.py environment variables (#3313)
2d6106b is described below

commit 2d6106b9f2f6d8a6d7b2100bb2a03a606cb7100c
Author: ocket8888 <oc...@gmail.com>
AuthorDate: Mon Feb 11 09:57:32 2019 -0700

    Ort.py environment variables (#3313)
    
    * ORT.py now implements all the same command line flags as the Perl script
    
    * ORT.py now implements all the same command line flags as the Perl script
    
    * ORT.py now uses the TO_* environment variables
---
 .../ort/traffic_ops_ort.configuration.rst          |  11 +-
 .../ort/traffic_ops_ort.main_routines.rst          |   9 +-
 .../development/ort/traffic_ops_ort.packaging.rst  |  10 +-
 .../development/ort/traffic_ops_ort.to_api.rst     |   4 +-
 .../development/ort/traffic_ops_ort.utils.rst      |  10 +-
 infrastructure/cdn-in-a-box/edge/run.sh            |   2 +-
 .../cdn-in-a-box/ort/traffic_ops_ort.crontab       |   2 +-
 .../cdn-in-a-box/ort/traffic_ops_ort/__init__.py   | 229 ++++++++++++++++++---
 .../ort/traffic_ops_ort/configuration.py           |  10 +-
 .../cdn-in-a-box/ort/traffic_ops_ort/to_api.py     |   3 +-
 10 files changed, 234 insertions(+), 56 deletions(-)

diff --git a/docs/source/development/ort/traffic_ops_ort.configuration.rst b/docs/source/development/ort/traffic_ops_ort.configuration.rst
index 7ae908a..9bb5920 100644
--- a/docs/source/development/ort/traffic_ops_ort.configuration.rst
+++ b/docs/source/development/ort/traffic_ops_ort.configuration.rst
@@ -13,13 +13,10 @@
 .. limitations under the License.
 ..
 
+**************************************
 traffic\_ops\_ort.configuration module
-======================================
-
-.. autodata:: traffic_ops_ort.configuration.HOSTNAME
-	:annotation:
-
+**************************************
 .. automodule:: traffic_ops_ort.configuration
 	:members:
-    :undoc-members:
-    :show-inheritance:
+	:undoc-members:
+	:show-inheritance:
diff --git a/docs/source/development/ort/traffic_ops_ort.main_routines.rst b/docs/source/development/ort/traffic_ops_ort.main_routines.rst
index 9d82c76..e81aee9 100644
--- a/docs/source/development/ort/traffic_ops_ort.main_routines.rst
+++ b/docs/source/development/ort/traffic_ops_ort.main_routines.rst
@@ -13,10 +13,11 @@
 .. limitations under the License.
 ..
 
+***************************************
 traffic\_ops\_ort.main\_routines module
-=======================================
+***************************************
 
 .. automodule:: traffic_ops_ort.main_routines
-    :members:
-    :undoc-members:
-    :show-inheritance:
+	:members:
+	:undoc-members:
+	:show-inheritance:
diff --git a/docs/source/development/ort/traffic_ops_ort.packaging.rst b/docs/source/development/ort/traffic_ops_ort.packaging.rst
index 7263168..bd78609 100644
--- a/docs/source/development/ort/traffic_ops_ort.packaging.rst
+++ b/docs/source/development/ort/traffic_ops_ort.packaging.rst
@@ -13,10 +13,10 @@
 .. limitations under the License.
 ..
 
+**********************************
 traffic\_ops\_ort.packaging module
-==================================
-
+**********************************
 .. automodule:: traffic_ops_ort.packaging
-    :members:
-    :undoc-members:
-    :show-inheritance:
+	:members:
+	:undoc-members:
+	:show-inheritance:
diff --git a/docs/source/development/ort/traffic_ops_ort.to_api.rst b/docs/source/development/ort/traffic_ops_ort.to_api.rst
index c1bc920..3eed8c9 100644
--- a/docs/source/development/ort/traffic_ops_ort.to_api.rst
+++ b/docs/source/development/ort/traffic_ops_ort.to_api.rst
@@ -13,9 +13,9 @@
 .. limitations under the License.
 ..
 
+********************************
 traffic\_ops\_ort.to\_api module
-================================
-
+********************************
 .. automodule:: traffic_ops_ort.to_api
     :members:
     :undoc-members:
diff --git a/docs/source/development/ort/traffic_ops_ort.utils.rst b/docs/source/development/ort/traffic_ops_ort.utils.rst
index ad7433a..fa911b2 100644
--- a/docs/source/development/ort/traffic_ops_ort.utils.rst
+++ b/docs/source/development/ort/traffic_ops_ort.utils.rst
@@ -13,10 +13,10 @@
 .. limitations under the License.
 ..
 
+******************************
 traffic\_ops\_ort.utils module
-==============================
-
+******************************
 .. automodule:: traffic_ops_ort.utils
-    :members:
-    :undoc-members:
-    :show-inheritance:
+	:members:
+	:undoc-members:
+	:show-inheritance:
diff --git a/infrastructure/cdn-in-a-box/edge/run.sh b/infrastructure/cdn-in-a-box/edge/run.sh
index d88c7a6..a5da036 100755
--- a/infrastructure/cdn-in-a-box/edge/run.sh
+++ b/infrastructure/cdn-in-a-box/edge/run.sh
@@ -72,7 +72,7 @@ until to-get "api/1.3/cdns/name/$CDN/sslkeys" && [[ "$(to-get api/1.3/cdns/name/
 done
 
 # Leaves the container hanging open in the event of a failure for debugging purposes
-traffic_ops_ort -k BADASS ALL "https://$TO_FQDN:$TO_PORT" "$TO_ADMIN_USER:$TO_ADMIN_PASSWORD" || { echo "Failed"; }
+traffic_ops_ort -kl ALL BADASS || { echo "Failed"; }
 
 envsubst < "/etc/cron.d/traffic_ops_ort-cron-template" > "/var/spool/cron/root" && rm -f "/etc/cron.d/traffic_ops_ort-cron-template"
 crontab "/var/spool/cron/root"
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort.crontab b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort.crontab
index 7adce29..8ee539d 100644
--- a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort.crontab
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort.crontab
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-*/1 * * * * /usr/bin/traffic_ops_ort -k --dispersion 0 SYNCDS ALL https://$TO_FQDN $TO_ADMIN_USER:$TO_ADMIN_PASSWORD >> /var/log/ort.log 2>> /var/log/ort.log
+*/1 * * * * . /to-access.sh; /usr/bin/traffic_ops_ort -kl ALL --dispersion 0 SYNCDS >> /var/log/ort.log 2>>&1
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/__init__.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/__init__.py
index ceb420b..89586c7 100644
--- a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/__init__.py
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/__init__.py
@@ -28,12 +28,38 @@ This package provides an executable script named :program:`traffic_ops_ort`
 
 Usage
 =====
-``traffic_ops_ort [-k] [--dispersion DISP] [--login_dispersion DISP] [--retries RETRIES] [--wait_for_parents INT] [--rev_proxy_disable] [--ts-root PATH] MODE LOG_LEVEL TO_URL LOGIN``
-
-``traffic_ops_ort [-v]``
-
-``traffic_ops_ort [-h]``
-
+There are two main ways to invoke :program:`traffic_ops_ort`. The first method uses what's referred
+to as the "legacy call signature" and is meant to match the Perl command line arguments.
+
+.. code-block:: text
+	:caption: Legacy Call Signature
+
+	traffic_ops_ort [-k] [-h] [-v] [--dispersion DISP] [--login_dispersion DISP]
+	         [--retries RETRIES] [--wait_for_parents INT] [--rev_proxy_disable]
+	         [--ts_root PATH] MODE LOG_LEVEL TO_URL LOGIN``
+
+The second method - called the "new call signature" - aims to reduce the complexity of the
+:term:`ORT` command line. Rather than require a URL and "login string" for connecting and
+authenticating with the Traffic Ops server, these pieces of information are optional and may be
+provided by the :option:`--to_url`, :option:`-u`/:option:`--to_user`, and
+:option:`-p`/:option:`--password` options, respectively. If they are NOT provided, then their values
+will be obtained from the :envvar:`TO_URL`, :envvar:`TO_USER`, and :envvar:`TO_PASSWORD` environment
+variables, respectively. Note that :program:`traffic_ops_ort` cannot be run using the new call
+signature without providing a definition for each of these, either on the command line or in the
+execution environment.
+
+.. code-block:: text
+	:caption: New call signature
+
+	traffic_ops_ort [-k] [-h] [-v] [--dispersion DISP] [--login_dispersion DISP]
+	     [--retries RETRIES] [--wait_for_parents INT] [--rev_proxy_disable]
+	     [--ts_root PATH] [-l LOG_LEVEL] [-u USER] [-p PASSWORD] [--to_url URL] MODE
+
+These two call signatures should not be mixed, and :program:`traffic_ops_ort` will exit with an
+error if they are.
+
+Arguments and Flags
+-------------------
 .. option:: -h, --help
 
 	Print usage information and exit
@@ -48,7 +74,8 @@ Usage
 
 .. option:: --dispersion DISP
 
-	Wait a random number between 0 and ``DISP`` seconds before starting. (Default: 300)
+	Wait a random number between 0 and ``DISP`` seconds before starting. This option *only* has any
+	effect if :option:`MODE` is ``SYNCDS``. (Default: 300)
 
 .. option:: --login_dispersion DISP
 
@@ -99,9 +126,11 @@ Usage
 		when possible. This will install packages, enable/disable system services, and will start or
 		restart Apache Traffic Server as necessary.
 
-.. option:: LOG_LEVEL
+.. option:: LOG_LEVEL, -l LOG_LEVEL, --log_level LOG_LEVEL
 
-	Sets the verbosity of output provided by :program:`traffic_ops_ort`. Must be one of:
+	Sets the verbosity of output provided by :program:`traffic_ops_ort`. This argument is positional
+	in the legacy call signature, but optional in the new call signature, wherein it has a default
+	value of "WARN". Must be one of (case-insensitive):
 
 	NONE
 		Will output nothing, not even fatal errors.
@@ -131,31 +160,90 @@ Usage
 
 	.. note:: All logging is sent to STDERR. INTERACTIVE :option:`MODE` prompts are printed to STDOUT
 
-.. option:: TO_URL
+.. option:: TO_URL, --to_url TO_URL
+
+	This must be at minimum an :abbr:`FQDN (Fully Qualified Domain Name)` that resolves to the
+	Traffic Ops server, but may optionally include the schema and/or port number. E.g.
+	``https://trafficops.infra.ciab.test:443``, ``https://trafficops.infra.ciab.test``,
+	``trafficops.infra.ciab.test:443``, and ``trafficops.infra.ciab.test`` are all acceptable, and
+	in fact are all equivalent. When given a value without a schema, HTTPS will be the assumed
+	protocol, and when a port number is not present, 443 will be assumed except in the case that
+	the schema *is* provided and is ``http://`` (case-insensitive) in which case 80 will be assumed.
 
-	This must be the full URL that refers to the Traffic Ops server, including schema and port
-	number (if needed). E.g. ``https://trafficops.infra.ciab.test:443``.
+	This argument is positional in the legacy call signature, but is optional in the new call
+	signature. When the new call signature is used and this option is not present on the command
+	line, its value will be obtained from :envvar:`TO_URL`. Note that :program:`traffic_ops_ort`
+	cannot be run using the new call signature unless this value is defined, either on the command
+	line or in the execution environment.
 
 .. option:: LOGIN
 
 	The information used to authenticate with Traffic Ops. This must consist of a username and a
-	password, delimited by a colon (``:``). E.g. ``admin:twelve``.
+	password, delimited by a colon (``:``). E.g. ``admin:twelve``. This argument is not used in the
+	new call signature, instead :option:`-u`/:option:`--to_user` and
+	:option:`-p`/:option:`--to_password` are used to separately set the authentication user and
+	password, respectively.
 
 	.. warning:: The first colon found in this string is considered the delimiter. There is no way
 		to escape the delimeter. This effectively means that usernames containing colons cannot be
 		used to authenticate with Traffic Ops, though passwords containing colons should be fine.
 
+.. option:: -u USER, --to_user USER
+
+	Specifies the username of the user as whom to authenticate when connecting to Traffic Ops. This
+	option is only available using the new call signature. If not provided when using said new call
+	signature, the value will be obtained from the :envvar:`TO_USER` environment variable. Note that
+	:program:`traffic_ops_ort` cannot be run using the new call signature unless this value is
+	defined, either on the command line or in the execution environment.
+
+.. option:: -p PASSWORD, --to_password PASSWORD
+
+	Specifies the password of the user identified by :envvar:`TO_USER` (or
+	:option:`-u`/:option:`--to_user` if overridden) to use when authenticating to Traffic Ops. This
+	option is only available using the new call signature. If not provided when using said new call
+	signature, the value will be obtained from the :envvar:`TO_PASSWORD`  environment variable. Note
+	that :program:`traffic_ops_ort` cannot be run using the new call signature unless this value is
+	defined, either on the command line or in the execution environment.
+
+Environment Variables
+---------------------
+.. envvar:: TO_URL
+
+	Should be set to the URL of a Traffic Ops server. This doesn't need to be a full URL, an
+	:abbr:`FQDN (Fully Qualified Domain Name)` will do just as well. It may also omit the port
+	number on which the Traffic Ops server listens for incoming connections - port 443 will be
+	assumed unless :envvar:`TO_URL` is prefixed by ``http://`` (case-insensitive), in which case
+	port 80 will be assumed. The value of this environment variable will only be considered if
+	:program:`traffic_ops_ort` was invoked using the new call signature, which allows it to be
+	overridden on the command line by the value of :option:`--to_url`.
+
+.. envvar:: TO_USER
+
+	The username to use when authenticating to the Traffic Ops server. The value of this environment
+	variable will only be considered if :program:`traffic_ops_ort` was invoked using the new call
+	signature, which allows it to be overridden on the command line by the value of
+	:option:`-u`/:option:`--to_user`.
+
+.. envvar:: TO_PASSWORD
+
+	The password to use when authenticating to the Traffic Ops server. The value of this environment
+	variable will only be considered if :program:`traffic_ops_ort` was invoked using the new call
+	signature, which allows it to be overridden on the command line by the value of
+	:option:`-p`/:option:`--to_password`.
+
 Module Contents
 ===============
 """
 
-__version__ = "0.0.5"
+__version__ = "0.1.0"
 __author__  = "Brennan Fieck"
 
 import argparse
 import datetime
 import logging
+import os
 import random
+import sys
 import time
 
 from requests.exceptions import RequestException
@@ -194,29 +282,82 @@ def doMain(args:argparse.Namespace) -> int:
 		logging.debug("%r", e, exc_info=True, stack_info=True)
 		return 1
 
-def main():
+_EPILOG = """traffic_ops_ort supports two calling conventions, one is intended to be fully
+compatible with the Perl implementation, while the other is intended to be an improvement over the
+former. Essentially this means that either the `Log_Level`, `Traffic_Ops_URL` and
+`Traffic_Ops_Login`` must all be given, or none of them. If none of them are given, the log level
+will be determined by the `-l`/`--log_level` option, the Traffic Ops server URL will be constructed
+from the information available in the `TO_URL` environment and/or the `--to_url` option, the
+Traffic Ops user will be determined from the information available in the `TO_USER` environment
+variable and/or the `-u`/`--to_user` option, and the Traffic Ops user's password will be determined
+from the information available in the `TO_PASSWORD` environment variable and/or the
+`-p`/`--to_password` option.
+""".replace('\n', ' ') + "\n\n" + ("Note that passing a negative integer to options that expect "
+                                   "integers will instead set them zero.")
+
+def main() -> int:
 	"""
 	The ORT entrypoint, parses argv before handing it off to :func:`doMain`.
+
+	:returns: An exit code for :program:`traffic_ops_ort`
 	"""
+	global _EPILOG
+
 	# I have no idea why, but the old ORT script does this on every run.
 	print(datetime.datetime.utcnow().strftime("%a %b %d %H:%M:%S UTC %Y"))
 
+	from .configuration import LogLevels, Configuration
+
+	runModesAllowed = {str(x) for x in Configuration.Modes}.union(
+	                  {str(x).lower() for x in Configuration.Modes})
+	logLevelsAllowed = {str(x) for x in LogLevels}.union({str(x).lower() for x in LogLevels})
+
 	parser = argparse.ArgumentParser(description="A Python-based TO_ORT implementation",
-	                                 epilog=("Note that passing a negative integer to options that "
-	                                         "expect integers will instead set them to zero."),
+	                                 epilog=_EPILOG,
 	                                 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
 
 	parser.add_argument("Mode",
 	                    help="REPORT: Do nothing, but print what would be done\n"\
-	                         "REPORT, INTERACTIVE, REVALIDATE, SYNCDS, BADASS")
-	parser.add_argument("Log_Level",
+	                         "REPORT, INTERACTIVE, REVALIDATE, SYNCDS, BADASS",
+	                    choices=runModesAllowed,
+	                    type=str)
+	parser.add_argument("legacy",
 	                    help="ALL/TRACE, DEBUG, INFO, WARN, ERROR, FATAL/CRITICAL, NONE",
+	                    metavar="Log_Level",
+	                    nargs="?",
+	                    action="append",
+	                    choices=logLevelsAllowed,
 	                    type=str)
-	parser.add_argument("Traffic_Ops_URL",
+	parser.add_argument("-l", "--log_level",
+	                    help="Sets the logging level. (Default: WARN)",
+	                    type=str,
+	                    choices=logLevelsAllowed)
+	parser.add_argument("legacy",
 	                    help="URL to Traffic Ops host. Example: https://trafficops.company.net",
+	                    metavar="Traffic_Ops_URL",
+	                    nargs="?",
+	                    action="append",
+	                    type=str)
+	parser.add_argument("--to_url",
+	                    help=("A URL or hostname - optionally with a port specification - that "
+	                          "points to a Traffic Ops server. e.g. `trafficops.infra.ciab.test` or"
+	                          " `https://trafficops.infra.ciab.test:443`. This overrides the TO_URL"
+	                          " environment variable"),
+	                    type=str)
+	parser.add_argument("legacy",
+	                    help="Example: 'username:password'",
+	                    metavar="Traffic_Ops_Login",
+	                    nargs="?",
+	                    action="append",
+	                    type=str)
+	parser.add_argument("-u", "--to_user",
+	                    help=("The username to use when authenticating to the Traffic Ops server. "
+	                          "This overrides the TO_USER environment variable."),
+	                    type=str)
+	parser.add_argument("-p", "--to_password",
+	                    help=("The password to use when authenticating to the Traffic Ops server. "
+	                          "This overrides the TO_PASSWORD environment variable."),
 	                    type=str)
-	parser.add_argument("Traffic_Ops_Login",
-	                    help="Example: 'username:password'")
 	parser.add_argument("--dispersion",
 	                    help="wait a random number between 0 and <dispersion> before starting.",
 	                    type=int,
@@ -250,4 +391,46 @@ def main():
 	                    version="%(prog)s v"+__version__,
 	                    help="Print version information and exit.")
 
-	exit(doMain(parser.parse_args()))
+	args = parser.parse_args()
+
+	# New call signature
+	if None in args.legacy:
+		if any(args.legacy):
+			print("Legacy mode call signature cannot be partial!", file=sys.stderr)
+			print("(Hint: use -h/--help for usage)", file=sys.stderr)
+			return 1
+
+		try:
+			args.to_url = args.to_url if args.to_url else os.environ["TO_URL"]
+			args.to_password = args.to_password if args.to_password else os.environ["TO_PASSWORD"]
+			args.to_user = args.to_user if args.to_user else os.environ["TO_USER"]
+		except KeyError as e:
+			print("Neither option nor environment variable defined for %s!" % e.args[0],
+			      file=sys.stderr)
+			print("(Hint: use -h/--help for usage)", file=sys.stderr)
+			return 1
+
+		args.log_level = args.log_level if args.log_level else "WARN"
+
+	# Illegal mixed call signature
+	elif (args.to_url is not None or
+	      args.to_user is not None or
+	      args.log_level is not None or
+	      args.to_password is not None):
+
+		print("Do not mix legacy call signature with new-style call signature!", file=sys.stderr)
+		print("(Hint: use -h/--help for usage)", file=sys.stderr)
+		return 1
+
+	# Legacy call signature
+	else:
+		args.log_level, args.to_url, login = args.legacy
+		try:
+			args.to_user, args.to_password = login.split(':')
+		except ValueError:
+			print("Invalid Traffic_Ops_Login format! Should be 'username:password'",file=sys.stderr)
+			print("(Hint: use -h/--help for usage)", file=sys.stderr)
+			return 1
+
+
+	return doMain(args)
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/configuration.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/configuration.py
index a98d076..6745146 100644
--- a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/configuration.py
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/configuration.py
@@ -113,7 +113,7 @@ class Configuration():
 		self.rev_proxy_disable = args.rev_proxy_disable
 		self.verify = not args.insecure
 
-		setLogLevel(args.Log_Level)
+		setLogLevel(args.log_level)
 
 		logging.info("Distribution detected as: '%s'", DISTRO)
 
@@ -128,12 +128,8 @@ class Configuration():
 		self.tsroot = parseTSRoot(args.ts_root)
 		logging.info("ATS root installation directory set to '%s'", self.tsroot)
 
-		self.useSSL, self.toHost, self.toPort = parseTOURL(args.Traffic_Ops_URL, self.verify)
-
-		try:
-			self.username, self.password = args.Traffic_Ops_Login.split(':')
-		except ValueError as e:
-			raise ValueError("Invalid login information, should be like 'username:password'.") from e
+		self.useSSL, self.toHost, self.toPort = parseTOURL(args.to_url, self.verify)
+		self.username, self.password = args.to_user, args.to_password
 
 
 	@property
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/to_api.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/to_api.py
index dff43cc..b1d063e 100644
--- a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/to_api.py
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/to_api.py
@@ -23,8 +23,9 @@ It extends the class provided by the official Apache Traffic Control Client.
 import typing
 import logging
 
-from requests.exceptions import RequestException
 from requests.compat import urljoin
+from requests.exceptions import RequestException
+
 from trafficops.tosession import TOSession
 from trafficops.restapi import LoginError, OperationError, InvalidJSONError