Commit Graph

67 Commits

Author SHA1 Message Date
Julia Kreger 74f05249d1 Drop parameters when connecting to a redirected endpoint
When redirected, the server *generally* returns a fully
formed URI, but does not really have to, so we may end up
in a "depending on how the redirect was triggered" would
result in the response handling.

Ultimately, any behavior which is not an fully formed URI
would be invalid.

But our code was taking the URI we got back, and would then
re-issue the request with a list of parameters with the new
URL. Duplicating the parameters on the URI.

Example of what was occuring, when only provision_state=active
was a parameter before the redirect:

/v1/nodes?provision_state=active&provision_state=active

Co-Authored-By: Kristi Nikolla <knikolla@bu.edu>
Co-Authored-By: Jay Faulkner <jay@jvf.cc>

Story: 2010029
Task: 45316
Change-Id: I4969a42ee651ac2c559e378d879b673a1d788c57
2023-10-06 16:21:02 +02:00
Vadym Markov c800dcee75 Keep request-id at redirect
Currently when redirects are used, the request id can get lost on redirect.
Proposed patch reuses req-id from redirect response and passes it to
actual request

Closes-Bug: #2000742
Change-Id: I98d5d4490b3d5667677cdd19f3c7b39abe6044ef
2023-05-27 13:04:05 +00:00
Stephen Finucane 192a27ae5f Remove six
This is no longer necessary since we only support Python 3.x.

A note is removed from requirements.txt since it's no longer relevant:
pip 20.3+ has a real dependency resolver.

Change-Id: Ie3006813a79fef1f128d388b906e4f1752347fa4
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
Co-Authored-By: Grzegorz Grasza <xek@redhat.com>
2022-12-14 10:47:25 +00:00
melanie witt bc491817e1 Allow logging of Content-Type text/plain
Noticed this while doing some local testing, if a WSGI app replies with
a text/plain content type to communicate a server error, we aren't able
to see the error response message when passing --debug to the
openstackclient, example:

  RESP: [500] Date: Thu, 01 Oct 2020 23:54:15 GMT Server: Apache/2.4.18
  (Ubuntu) Content-Type: text/plain; charset=UTF-8 Connection: close
  Transfer-Encoding: chunked
  RESP BODY: Omitted, Content-Type is set to text/plain; charset=UTF-8.
  Only application/json responses have their bodies logged.

Change-Id: Ibfd46c7725bd0aa26f1f80b0e8fc6eda2ac2e090
2022-04-29 15:57:52 +00:00
Goutham Pacha Ravi 112bcae1fb Specify manila microversion header
Manila API honors a "X-OpenStack-Manila-API-Version"
header to specify microversions.

It may support the OpenStack-API-Version header
in a future release, however, we'll need to maintain
backwards compatibility with the existing API.

Change-Id: Ia2e62d3a11a08adeb6d488b7c9b365f7ff2be3c8
2021-02-18 08:38:29 -08:00
Zuul e96c2102ad Merge "Use unittest.mock instead of third party mock" 2020-06-05 04:21:48 +00:00
Ghanshyam Mann c00fca4a09 Make header Case Insensitive
In case of global-request-id request, Adapter
send two global request id header
 - "X-OpenStack-Request-ID"
 - "X-Openstack-Request-Id".

Example: https://zuul.opendev.org/t/openstack/build/c5b1debf78df4aa3bdda34f0b4c53c37/log/testrepository.subunit#2385

This is becasue of the header not being Case Insensitive
and end up with two different name of same header with difference
of cap 'D'.

Unit test for whether request global-request-id has precedence
over adapter fail many times because of how different python version
treat the dict. py3.6 and above are all good as dict maintain the
insertion ordered but py3.5 can fail it any time.

We can see consistent failure in py35 jobs:
- https://review.opendev.org/#/c/730687/

Let's make the headers always Case Insensitive which is
what RFC says.

Change-Id: Iba707dd0506d22e144aca4fdfc9b140c8e37ae02
Closes-Bug: #1881351
2020-05-29 17:17:11 -05:00
Sean McGinnis edc2ae4249
Use unittest.mock instead of third party mock
Now that we no longer support py27, we can use the standard library
unittest.mock module instead of the third party mock lib.

Change-Id: I07d61e1a8f18d65acdf86cdd61f7d9e28157f1d7
Signed-off-by: Sean McGinnis <sean.mcginnis@gmail.com>
2020-05-29 10:37:58 -05:00
Zuul 5e5185f80f Merge "Allow initializing session with connection retries" 2019-10-09 20:23:21 +00:00
Zuul c102a7e9f5 Merge "Cleanup session on delete" 2019-10-05 09:38:48 +00:00
Colleen Murphy 8b06c57292 Simplify session logger object tests
With the requests-mock logger now configured to log the request[1],
checking that the logger output does *not* contain the request is
invalid. Simplify these two tests by omitting the assertion.

[1] https://github.com/jamielennox/requests-mock/pull/93

Closes-bug: #1842978

Change-Id: If3c0447502917bce831d3e9f7ae4c31374dd4380
2019-09-05 13:53:53 -07:00
Rabi Mishra 373cbdbda8 Allow initializing session with connection retries
Though we can now set ``connect_retires`` while creating an adapter object,
that  would allow retries in case of connection timeout (ex. with session
clients derived from Adapater/LegacyJsonAdapater), it can't be used in
certain scenarios like endpoint discovery with auth plugin get_discovery()
or getting AccessInfo with get_access()/get_auth_ref().

Having ``connect_retries`` in Session constructor would allow users
with option of setting it when creating session objects (if they want)
and can be overridden per service with the adapter interface.

This commit also changes the default value of ``connect_retries`` from
0 to None to allow for adapter's to override retries on the session
object.

Depends-On: https://review.opendev.org/#/c/680497/

Change-Id: Iffb671fefae23926b1f09017d9db438341eae238
Partial-Bug: #1840235
2019-09-05 19:31:22 +00:00
Alex Schultz b2b5ad3cb1 Cleanup session on delete
If an external session object was not passed to the Session class, we
create a requests.Session() on our own. Once this is used, it may still
have an open connection when the auth Session is closed. We need to
handle the closing of the requests.Session() ourselves if we created
one. If you do not close it, a ResourceWarning may be reported about the
socket that is left open. If a session object is provided, we do not
attempt to close it as it will be up to the code consuming keystoneauth
to properly handle cleaning up the provided session.

Change-Id: I590755d665b371c76ba8e02836d81d41a95ac601
Closes-Bug: #1838704
2019-08-26 08:12:27 -06:00
Dmitry Tantsur bca9ee7d3c Allow requesting fixed retry delay instead of exponential
Clients like ironicclient and swiftclient use fixed delay for their
build-in retry functionality. To replace it without changing behavior
we need a similar feature.

Change-Id: I1f9de98dae5719842f03d45e5a9d724199d5718b
2019-07-29 13:07:38 +02:00
Eric Fried df57e0ec3b Add a per-request global_request_id
Adapter.__init__ takes a global_request_id which causes the
X-Openstack-Request-Id header to be set on each request. This is fine if
the Adapter is used for only one "request" (in the sense of e.g. "a
server create" -- see [1]), but is too broad if the Adapter is reused
for multiple requests. For example, Nova's SchedulerReportClient (used
to communicate with Placement) creates a single instance of Adapter for
the life of the process [2][3][4]. Openstack SDK's Proxy objects [5]
endure for the life of a Connection.

So what is needed is a way to manage the X-Openstack-Request-Id header
on a per-request basis.

This commit adds a global_request_id kwarg to
keystoneauth1.session.Session.request, which is the funnel point for all
requests coming through Adapter as well as Session itself. (All the
methods feeding into that one already accept and pass through arbitrary
**kwargs.) If present, the value in the X-Openstack-Request-Id header is
set accordingly. Note that this will *override*
Adapter.global_request_id, which is exactly what we want, as described
above.

[1] http://specs.openstack.org/openstack/oslo-specs/specs/pike/global-req-id.html
[2] bea9058f02/nova/scheduler/client/report.py (L200)
[3] bea9058f02/nova/scheduler/client/report.py (L243)
[4] bea9058f02/nova/utils.py (L1219-L1221)
[5] bf6651f149/openstack/proxy.py (L114)

Change-Id: Ied73320fcd813ae796e40cbdb30717900486b92c
2019-07-11 10:35:44 -05:00
Dmitry Tantsur 34c005ae5f Limit interval between retries to 1 minute
Currently it grows exponentially, exceeding 1 hour after 15 retries.
While we don't expect people to have so many retries, we should not
let them shoot their legs.

Change-Id: I01dfaa1c379340a0d41fcfdb07298fdef6110941
2019-06-19 15:28:35 +02:00
Michael McCune 96559d6009 add a handler for unknown HTTP errors
This change adds logic to handle a situation where an error response has
been received by HTTP but its body schema is an unknown format.

This issue came up during a review of related changes:
https://review.opendev.org/#/c/662281/
https://review.opendev.org/#/c/662281/7/keystoneauth1/exceptions/http.py

Change-Id: I21a33052e951f515988fdfd8ab1f42440ca9d4f8
2019-06-04 16:03:33 -04:00
Michael McCune 01d2da9e47 add handling for multiple error returns
This change adds logic to the `exceptions.from_response` to handle
errors formatted in accordance with the API-SIG guidelines. When there
are multiple errors returned, only the first error will be included in
the exception with a note informing that there were more errors.

API SIG guideline:
https://specs.openstack.org/openstack/api-sig/guidelines/errors.html

email thread for content:
http://lists.openstack.org/pipermail/openstack-discuss/2019-May/006377.html

related neutron bug:
https://bugs.launchpad.net/neutron/+bug/1828543

Change-Id: I1f06c2cd5c4e93e04582d4ffbb434db92010d712
2019-06-03 11:09:34 -04:00
Monty Taylor 09934718f7 Add support for client-side rate limiting
shade/openstacksdk has implemented client-side rate limiting on top of
keystoneauth for ages and uses it extensively in nodepool. As part of an
effort to refactor that code a new approach was devised which was much
simpler and therfore suitable for inclusion in keystoneauth directly.

The underlying goal is two-fold, but fundamentally is about allowing a
user to add some settings so that they can avoid slamming their cloud.
First, allow a user to express that they never want to exceed a given
rate. Second, allow a user to limit the number of concurrent requests
allowed to be in flight.

The settings and logic are added to Adapter and not Session so that the
settings can easily be per-service. There is no need to block requests
to nova on a neutron rate limit, after all.

Co-Authored-By: Ian Wienand <iwienand@redhat.com>
Needed-By: https://review.openstack.org/604926
Change-Id: Ic831e03a37d804f45b7ee58c87f92fa0f4411ad8
2019-02-28 22:14:24 +00:00
Gage Hugo ccf6cb7903 Change log hashing to SHA256
With the recent Bandit update[0], the usage of SHA1 is now being
tagged as an issue. This changes the hashing of logs to SHA256
instead of SHA1.

Change-Id: Icde62b8d5ff78b4155e9df8231d63be3ecc53520
2018-08-17 12:35:47 -05:00
Eric Fried 51bfa030b1 raise_exc default in Adapter
It can be annoying to have to say raise_exc=False (or use try/except) on
every call when talking to an API where 4xx response codes are
useful/normal/informative or where the preferred coding style is to use
conditionals rather than try/except.

With this change, the Adapter constructor takes a new kwarg, raise_exc.
It defaults to None, and the existing behavior is unchanged.  If set to
a boolean value, that is used as the default for requests.  Specifying
raise_exc to the primitives (get, head, put, post, patch, delete,
request) at any point along the chain will still take precedence.

Change-Id: Ie291c3cb891467728d8ca33cf62afdab37c82f34
Closes-Bug: #1776501
2018-06-12 10:48:39 -05:00
Dmitry Tantsur 3c2cf44e1c Add optional support for retrying certain HTTP codes
Ironic commonly returns HTTP 409 when a node is locked by another routine
and HTTP 503 when the conductor has no free threads to process the request.
Currently it is managed by custom code in ironicclient and openstacksdk,
this change will allow to move it to Session itself.

Change-Id: I04e356e7856b020cd20aa598e291ef31e02730d2
2018-05-29 14:54:56 +02:00
Zuul cc912f0500 Merge "Collect timing information for API calls" 2018-05-17 21:06:52 +00:00
Monty Taylor 244780fba8
Collect timing information for API calls
python-openstackclient does this in a wrapper class around Session,
and openstacksdk does something similar that could be removed if support
were directly in keystoneauth.

Add this so that we can remove the custom wrapper/manipulation in
openstackclient and openstacksdk.

Change-Id: Icf00c66f57d20d2cef724c233160d3b1e0d52102
2018-05-16 15:41:59 -05:00
Brian Rosmaita 35de6ebe93
Fix logging of encoded headers
A change introduced in 3.5.0 sorts headers, but runs into a problem
when the headers are bytes, such as the headers provided by the
python-glanceclient.

requests expects headers to be str type in both python2 and python3.
This means in python2 we need to encode unicode objects as ASCII (the
encoding that should be used for HTTP headers) and in python3 we need to
decode bytes as ASCII into str.

Change-Id: Ib81497c3a873616c22ba68256c596a6fb113e11e
Closes-bug: #1766235
2018-05-15 09:29:43 -05:00
Zuul 43698b65c9 Merge "Split request logging into four different loggers" 2018-02-15 21:14:28 +00:00
Monty Taylor 56b2c89c39
Split request logging into four different loggers
Python logging is pretty amazingly flexible, and allows us to emit
to arbitrary logging domains so that a consumer can direct log output
with specificity.

Turning on HTTP debug logging currently produces an avalanche of output,
when sometimes just seeing that the requests were made and responded to
is perfectly fine.

Split the loggers used into four - one for request ids, one for request
commands, one for response headers and one for response body content.
Make them subloggers of keystoneauth.session so that if a user does nothing,
their existing logging config will be unchanged.

If someone passes in a logger, behave as before logging all things to
the provided logger.

While we're at it, document this in the using-sessions document, so that
people know that the loggers exist and what they do.

NOTE:
The tox (>=1.7.0) by default sets a random python hash seed which
causes ordering of dicts and sets to be different between tests runs.
Disabled the random python hash seed by setting PYTHONHASHSEED=0 to
fix the random failure of below test:

keystoneauth1.tests.unit.test_session.SessionAuthTests.
test_split_loggers

The PYTHONHASHSEED=0 is removed in the followup patch so that we can
separate the tracking down of ordering issues in tests from this patch.

Change-Id: Ide7dac8adf5c76c9019c35867cda632aff39770f
2018-01-31 11:51:59 -06:00
Monty Taylor c56f4f7e40 Shift additional_user_agent in the stack
The additional_user_agent is intended for things, such as
os-client-config, that sit somewhere in the stack between keystoneauth
and the actual client. So according to jamielennox in irc, it should be:

  app client *additional_user_agent keystoneauth requests

The current logic puts additional_user_agent between app and client,
leading to things that look like this:

  "User-Agent: v.py/1 os-client-config/1.26.1 shade/1.19.1
   keystoneauth1/2.18.0 python-requests/2.13.0 CPython/2.7.12"

Which is a bit off.

Change-Id: Iddfbeab322a39d3ba893a15aabb4c79050526451
2017-12-22 14:22:19 +01:00
Jenkins 353b926042 Merge "Fixed minor review comments and updated docs" 2017-07-20 21:55:44 +00:00
Monty Taylor 5058d40c51 Fixed minor review comments and updated docs
The previous microversion patch had some review comments from samuel and
colleen that this addresses. Also, add a release note.

Change-Id: Id83643ee5a00abc5134a88dfa5bc8ddb4f5a247a
2017-07-20 18:36:12 +00:00
Eric Fried 699fac136f Discourage 'version' and accept 'M.latest'
We're discouraging the use of the ambiguous and difficult-to-understand
'version' parameter in new discovery methods, instead encouraging the
use of min_version and max_version.

In order to make it possible to get the same functionality, though, we
need a way to say the same thing as version="M.m", which actually means,
"min version is M.m, and max version is the latest within major version
M".

Introducing 'latest' syntax, which can be used in various ways,
including:

min_version='2.3', max_version='2.latest'

...which is equivalent to the old school version='2.3'

Change-Id: Ife842333e25c33e54bbae4c1adb101014cb8e8db
2017-07-19 12:38:14 -05:00
Monty Taylor 218adc333e
Add ability to specify a microversion in a request
The user now has the ability to know what microversions are available,
but needs to be able to send a microversion header with their request.

Add a microversion parameter to Session that will construct and send the
header. The microversion header requires a service_type. One should be
available but it's possible for it to be missing if someone is using an
endpoint_override. Provide a parameter to let the user specify a
service_type for the microversion call in such cases.

Change-Id: I63cdd67701749630228f9496eda82b3c8747a608
2017-07-19 02:51:49 +09:00
Sean Dague 0906fb0424 Add global_request_id param to Adapter constructor
In order to make it easier for projects to enable global_request_id
passing, make it something the Adapter understands directly, so that
the logic of adding extra headers doesn't need to be in every client.

Part of the push to enable global_request_id throughout OpenStack.

oslo spec I65de8261746b25d45e105394f4eeb95b9cb3bd42

Change-Id: Ic75be3acb8b77aae8da631e3c4cd6f545a9a35cb
2017-05-25 08:47:07 -04:00
Jenkins 9365dbeb6d Merge "Correctly Omit Response Body in Debug Mode" 2017-01-18 03:15:24 +00:00
Jenkins 8a7bd461f4 Merge "Log request-id for each api call" 2017-01-17 22:09:07 +00:00
Samuel Pilla ed6ae95fa2 Correctly Omit Response Body in Debug Mode
A response with header Content-Type set to "application/json; charset=UTF-8"
would be omitted but not correctly logged. This patch set correctly omits
and logs a response with the mentioned header.

Co-Authored-By: Tin Lam <tinlam@gmail.com>
Change-Id: I21a185db4ca55ff16dba60f85bb229ffdacc2afa
Closes-Bug: #1656981
2017-01-17 09:29:46 -06:00
Jamie Lennox d73fd3ee84 Only log application/json in session to start
When whitelisting content types to debug print from session we chose
application/json and application/text. application/text is not a real
mime type, text is typically text/plain.

Rather than guess at mime types only print application/json to start
with, but make it easy for additional types to be added later.

Change-Id: Ica5fee076cdab8b1d5167161d28af7313fad9477
Related-Bug: 1616105
2017-01-10 05:45:13 +00:00
Tin Lam 9d3ae3ef94 X-Serivce-Token should be hashed in the log
Currently, logs display the hash values of X-Auth-Token,
Authorization, and X-Subject-Token, but not the value of
the X-Service-Token.  This patch set adds the X-Service-Token
to the list of header fields to be hashed for logging purposes.

Change-Id: I4d996a2631f61a2c9bbbc7f959e97c7279be023d
Closes-Bug: #1654847
2017-01-09 16:08:20 +00:00
Abhishek Kekane af658d0686 Log request-id for each api call
Added support to log 'X-Openstack-Request-Id' or
'X-Compute-Request-Id' in case of Nova for each api call.

If any python-*client which is using session is used from
command line then following log will be logged on console
if --debug flag is used.

DEBUG (session:350) GET call to compute for
http://10.232.48.201:8774/v2.1/servers/detail used
request id req-c54b8f3e-a7e4-4085-a5e3-fd5244ef3ce5

If any python-*client which is using session  is used in
applications (e.g. Nova) then following log message will be
logged in service logs.

DEBUG keystoneauth.session
[req-a6929d46-765c-44a9-8370-49ff0f1958ca admin admin] GET call
to network for
http://10.232.48.201:9696/v2.0/security-groups.json?id=040cc729-9086-4f41-8977-acb4ef71c7de used request id req-de6bfe07-22ac-4940-b65e-367cb0e8102d

DocImpact:
To use this feature user need to set 'default_log_levels' in third
party application. For example in nova.conf 'default_log_levels'
should be set as below:

default_log_levels = keystoneauth1=DEBUG

Closes-Bug: #1605488
Change-Id: If0c5a4eb7d51c601ba38149f846ebcd6116d18be
2017-01-06 13:09:16 +05:30
Samuel de Medeiros Queiroz f345559a06 Prevent MemoryError when logging response bodies
Response bodies are loaded into memory prior to
being logged.

Loading huge response bodies may result in a
MemoryError.

This patch proposes that only JSON and TEXT
responses be logged, i.e when the Content-Type
header is application/json or application/text.

Responses that do not include or have a different
Content-Type header will have their body omitted.

Closes-bug: 1616105

Change-Id: I93b6fff73368c4f58bdebf8566c4948b50980cee
2017-01-04 04:52:06 +00:00
Jenkins 459f3c0926 Merge "Replace six.iteritems() with .items()" 2016-12-16 04:11:33 +00:00
gengchc2 a00b8d844d Replace six.iteritems() with .items()
1.As mentioned in [1], we should avoid using
six.iteritems to achieve iterators. We can
use dict.items instead, as it will return
iterators in PY3 as well. And dict.items/keys
will more readable. 2.In py2, the performance
about list should be negligible, see the link [2].
[1] https://wiki.openstack.org/wiki/Python3
[2] http://lists.openstack.org/pipermail/openstack-dev/2015-June/066391.html

Change-Id: I9f8f2c35f0d45d866076507a3a167aaafb8382e5
2016-12-09 10:59:00 +08:00
Jamie Lennox c5bac3a32c Don't issue deprecation warning when nesting adapters
Auth token middleware does a bit of a hack where it passes an Adapter in
as a session to the client. This is useful there because we need to know
much more about the authentication information than we do in most
clients.

We should look at fixing this in auth_token middleware, however for now
we shouldn't issue a deprecation warning when a user passes an Adapter
as a session object because this has always been designed to work - just
not something we recommend.

Change-Id: If7ebe59d5908275e607f32244027c8e6f3d1e157
Closes-Bug: #1647230
2016-12-06 09:14:44 +11:00
Jamie Lennox 57f8d2cde5 Allow setting client_name, client_version on adapter
You can pass client_name and client_version to Adapter.__init__ but for
most clients this means overriding Adapter.__init__ and setdefault()-ing
the client_name and version.

As most clients already override the Adapter object it'd be easier if
they could just set these values on the class as they are not going to
change between instances.

Change-Id: I301a7f77c8cf423bc1d45e3dcbb2325f6853b9a9
2016-10-20 02:15:42 +00:00
Mike Fedosin ab39cf0667 Prevent changing content type in request
Now if body contains json, its content type forcibly
changes to application/json, which is not correct in
some case, like json-patch request.

This code fixes this situation and sets application/json
contnent type only if this header hasn't been set before.

Change-Id: I4e0c44d444519f056dfa48c9603dbc3ca6b01822
Closes-bug: #1634110
2016-10-17 15:54:45 +03:00
Jamie Lennox eb5571a6ca Allow specifying client and service info to user_agent
Allow specifying a service name and version to the session and a client
name and version to the adapter. The way this will work is that
libraries such as keystoneclient will pass client_name and
client_version when creating their adapter. Then when nova or another
service creates a session it will provide the service name and version.
The combination of these will be used to provide a meaningful user
agent.

Change-Id: Ibe516d9b248513579d5e8ca94015c4ae9c00f3f9
Closes-Bug: #1614846
2016-10-07 09:53:50 +11:00
Alex Oughton e3009ab365 Disables TCP_KEEPCNT when using Windows Subsystem for Linux
The Windows Subsystem for Linux is not a complete implementation
of the Linux APIs, and setting TCP_KEEPCNT is currently
unimplmenented. Attempting to use this option will cause HTTP
connections to fail. This change checks if we are running under
WSL, and disables changing TCP_KEEPCNT parameters if so.

Change-Id: Ic8b41dea2a75660d9adbce88a00a0fe703a4d120
Closes-Bug: #1614688
2016-08-23 03:36:45 +00:00
Alexey Stepanov 837118393c add status code 308 to _REDIRECT_STATUSES
add status code 308 to _REDIRECT_STATUSES as designed by rfc7238
Closes-bug: 1610914

Change-Id: I81ce137dad07e76a0f0c227dc8b263eec64fff7a
2016-08-10 21:40:36 +00:00
Matt Mulsow 4a0ac4583b User-agent header shouldn't start with a space
If the application name, sys.argv[0], is an empty string, like when
called from the Ansible os_network module, then keystoneauth (with
the new requests 2.11.0) will raise an exception saying:

Invalid return character or leading space in header: User-Agent

This comes from keystoneauth trying to prepend the empty module
name to the default user agent, which leads to it sending a
User-Agent header that starts with a blank space. This was fine
until the new requests 2.11.0 was released which errors if header
values start with a leading space.

With this change, if sys.argv[0] is an empty string we'll just use
the DEFAULT_USER_AGENT and not try to prepend a calling module.

Closes-Bug: #1611426

Change-Id: I56d3e352dce7628add0479b3333a880700844ebc
Signed-off-by: Matt Mulsow <mamulsow@us.ibm.com>
2016-08-09 10:57:10 -05:00
Brant Knudson c9ae7067bd Add tests for user-agent with odd sys.argv
There was no test that verified that when sys.argv is an empty
list or when sys.argv[0] is an empty string that the default
user-agent value is constructed as expected.

Change-Id: Iacf1557b6dbf48bf6bfb59d7cfbfec14e4fa8e56
Related-Bug: 1611426
2016-08-09 10:47:47 -05:00