Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update clients to get bug fixes in python client #640

Merged
merged 2 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion azure-devops/azext_devops/devops_sdk/_file_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def load(self):
try:
if os.path.isfile(self.file_name):
if self.max_age > 0 and os.stat(self.file_name).st_mtime + self.max_age < time.time():
logger.debug('Cache file expired: %s', file=self.file_name)
logger.debug('Cache file expired: %s', self.file_name)
os.remove(self.file_name)
else:
logger.debug('Loading cache file: %s', self.file_name)
Expand Down
19 changes: 12 additions & 7 deletions azure-devops/azext_devops/devops_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def add_user_agent(self, user_agent):
if user_agent is not None:
self.config.add_user_agent(user_agent)

def _send_request(self, request, headers=None, content=None, **operation_config):
def _send_request(self, request, headers=None, content=None, media_type=None, **operation_config):
"""Prepare and send request object according to configuration.
:param ClientRequest request: The request object to be sent.
:param dict headers: Any headers to add to the request.
Expand All @@ -57,16 +57,20 @@ def _send_request(self, request, headers=None, content=None, **operation_config)
or (TRACE_ENV_VAR_COMPAT in os.environ and os.environ[TRACE_ENV_VAR_COMPAT] == 'true'):
print(request.method + ' ' + request.url)
logger.debug('%s %s', request.method, request.url)
logger.debug('Request content: %s', content)
if media_type is not None and media_type == 'application/json':
logger.debug('Request content: %s', content)
response = self._client.send(request=request, headers=headers,
content=content, **operation_config)
logger.debug('Response content: %s', response.content)
if ('Content-Type' in response.headers
and response.headers['Content-Type'].startswith('application/json')):
logger.debug('Response content: %s', response.content)
if response.status_code < 200 or response.status_code >= 300:
self._handle_error(request, response)
return response

def _send(self, http_method, location_id, version, route_values=None,
query_parameters=None, content=None, media_type='application/json', accept_media_type='application/json', if_match=None):
query_parameters=None, content=None, media_type='application/json', accept_media_type='application/json',
additional_headers=None):
request = self._create_request_message(http_method=http_method,
location_id=location_id,
route_values=route_values,
Expand All @@ -85,8 +89,9 @@ def _send(self, http_method, location_id, version, route_values=None,
# Construct headers
headers = {'Content-Type': media_type + '; charset=utf-8',
'Accept': accept_media_type + ';api-version=' + negotiated_version}
if if_match:
headers['if-match'] = if_match
if additional_headers is not None:
for key in additional_headers:
headers[key] = str(additional_headers[key])
if self.config.additional_headers is not None:
for key in self.config.additional_headers:
headers[key] = self.config.additional_headers[key]
Expand All @@ -96,7 +101,7 @@ def _send(self, http_method, location_id, version, route_values=None,
headers['X-VSS-ForceMsaPassThrough'] = 'true'
if Client._session_header_key in Client._session_data and Client._session_header_key not in headers:
headers[Client._session_header_key] = Client._session_data[Client._session_header_key]
response = self._send_request(request=request, headers=headers, content=content)
response = self._send_request(request=request, headers=headers, content=content, media_type=media_type)
if Client._session_header_key in response.headers:
Client._session_data[Client._session_header_key] = response.headers[Client._session_header_key]
return response
Expand Down
33 changes: 32 additions & 1 deletion azure-devops/azext_devops/devops_sdk/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from .v5_0.client_factory import ClientFactoryV5_0
from .v5_1.client_factory import ClientFactoryV5_1


logger = logging.getLogger(__name__)


Expand All @@ -24,6 +23,7 @@ class Connection(object):

def __init__(self, base_url=None, creds=None, user_agent=None):
self._config = ClientConfiguration(base_url)
self._config.credentials = creds
self._addition_user_agent = user_agent
if user_agent is not None:
self._config.add_user_agent(user_agent)
Expand All @@ -35,6 +35,7 @@ def __init__(self, base_url=None, creds=None, user_agent=None):
self.clients = ClientFactory(self)
self.clients_v5_0 = ClientFactoryV5_0(self)
self.clients_v5_1 = ClientFactoryV5_1(self)
self.use_fiddler = False

def get_client(self, client_type):
"""get_client.
Expand All @@ -57,6 +58,8 @@ def _get_client_instance(self, client_class):
url = self._get_url_for_client_instance(client_class)
client = client_class(url, self._creds)
client.add_user_agent(self._addition_user_agent)
if self.use_fiddler:
self._configure_client_for_fiddler(client)
return client

def _get_url_for_client_instance(self, client_class):
Expand All @@ -74,16 +77,35 @@ def _get_url_for_client_instance(self, client_class):
for resource_area in resource_areas:
if resource_area.id.lower() == resource_id.lower():
return resource_area.location_url

# Check SPS deployment level for the resource area
resource_area = self._get_deployment_resource_area_from_sps(resource_id)
if resource_area is not None:
return resource_area.location_url

raise AzureDevOpsClientRequestError(('Could not find information for resource area {id} '
+ 'from server: {url}').format(id=resource_id,
url=self.base_url))

def _get_deployment_resource_area_from_sps(self, resource_id):
resource_id = resource_id.lower()
if resource_id in _deployment_level_resource_areas:
return _deployment_level_resource_areas[resource_id]
location_client = LocationClient(sps_url, self._creds)
if self.use_fiddler:
self._configure_client_for_fiddler(location_client)
resource_area = location_client.get_resource_area(area_id=resource_id)
_deployment_level_resource_areas[resource_id] = resource_area
return resource_area

def authenticate(self):
self._get_resource_areas(force=True)

def _get_resource_areas(self, force=False):
if self._resource_areas is None or force:
location_client = LocationClient(self.base_url, self._creds)
if self.use_fiddler:
self._configure_client_for_fiddler(location_client)
if not force and RESOURCE_FILE_CACHE[location_client.normalized_url]:
try:
logger.debug('File cache hit for resources on: %s', location_client.normalized_url)
Expand All @@ -109,3 +131,12 @@ def _get_resource_areas(self, force=False):
@staticmethod
def _combine_url(part1, part2):
return part1.rstrip('/') + '/' + part2.strip('/')

@staticmethod
def _configure_client_for_fiddler(client):
client.config.connection.verify = False
client.config.proxies.add(protocol='https', proxy_url='https://127.0.0.1:8888')


_deployment_level_resource_areas = {}
sps_url = 'https://app.vssps.visualstudio.com'
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, base_url=None, creds=None):
self._serialize = Serializer(client_models)
self._deserialize = Deserializer(client_models)

resource_area_identifier = None
resource_area_identifier = '8ccfef3d-2b87-4e99-8ccb-66e343d2daa8'

def get_profile(self, id, details=None, with_attributes=None, partition=None, core_attributes=None, force_refresh=None):
"""GetProfile.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,16 @@ def create_or_update_page(self, parameters, project, wiki_identifier, path, vers
query_parameters['path'] = self._serialize.query('path', path, 'str')
if comment is not None:
query_parameters['comment'] = self._serialize.query('comment', comment, 'str')
additional_headers = {}
if version is not None:
additional_headers['If-Match'] = version
content = self._serialize.body(parameters, 'WikiPageCreateOrUpdateParameters')
response = self._send(http_method='PUT',
location_id='25d3fbc7-fe3d-46cb-b5a5-0b6f79caf27b',
version='5.0',
route_values=route_values,
query_parameters=query_parameters,
additional_headers=additional_headers,
content=content)
response_object = models.WikiPageResponse()
response_object.page = self._deserialize('WikiPage', response)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,14 @@ def get_widgets(self, team_context, dashboard_id, eTag=None):
route_values['team'] = self._serialize.url('team', team, 'string')
if dashboard_id is not None:
route_values['dashboardId'] = self._serialize.url('dashboard_id', dashboard_id, 'str')
additional_headers = {}
if eTag is not None:
additional_headers['ETag'] = eTag
response = self._send(http_method='GET',
location_id='bdcff53a-8355-4172-a00a-40497ea23afc',
version='5.0-preview.2',
route_values=route_values)
route_values=route_values,
additional_headers=additional_headers)
response_object = models.WidgetsVersionedList()
response_object.widgets = self._deserialize('[Widget]', self._unwrap_collection(response))
response_object.eTag = response.headers.get('ETag')
Expand Down Expand Up @@ -422,11 +426,15 @@ def replace_widgets(self, widgets, team_context, dashboard_id, eTag=None):
route_values['team'] = self._serialize.url('team', team, 'string')
if dashboard_id is not None:
route_values['dashboardId'] = self._serialize.url('dashboard_id', dashboard_id, 'str')
additional_headers = {}
if eTag is not None:
additional_headers['ETag'] = eTag
content = self._serialize.body(widgets, '[Widget]')
response = self._send(http_method='PUT',
location_id='bdcff53a-8355-4172-a00a-40497ea23afc',
version='5.0-preview.2',
route_values=route_values,
additional_headers=additional_headers,
content=content)
response_object = models.WidgetsVersionedList()
response_object.widgets = self._deserialize('[Widget]', self._unwrap_collection(response))
Expand Down Expand Up @@ -499,11 +507,15 @@ def update_widgets(self, widgets, team_context, dashboard_id, eTag=None):
route_values['team'] = self._serialize.url('team', team, 'string')
if dashboard_id is not None:
route_values['dashboardId'] = self._serialize.url('dashboard_id', dashboard_id, 'str')
additional_headers = {}
if eTag is not None:
additional_headers['ETag'] = eTag
content = self._serialize.body(widgets, '[Widget]')
response = self._send(http_method='PATCH',
location_id='bdcff53a-8355-4172-a00a-40497ea23afc',
version='5.0-preview.2',
route_values=route_values,
additional_headers=additional_headers,
content=content)
response_object = models.WidgetsVersionedList()
response_object.widgets = self._deserialize('[Widget]', self._unwrap_collection(response))
Expand Down
Loading