class PoolManager(BaseManager):
    """ Manage DevOps Pools

    Attributes:
        See BaseManager
    """
    def __init__(self,
                 base_url='https://{}.visualstudio.com',
                 creds=None,
                 organization_name="",
                 project_name=""):
        """Inits PoolManager"""
        super(PoolManager, self).__init__(creds,
                                          organization_name=organization_name,
                                          project_name=project_name)
        base_url = base_url.format(organization_name)
        self._config = Configuration(base_url=base_url)
        self._client = ServiceClient(creds, self._config)
        client_models = {
            k: v
            for k, v in models.__dict__.items() if isinstance(v, type)
        }
        self._deserialize = Deserializer(client_models)
        self._user_mgr = UserManager(creds=self._creds)

    def list_pools(self):
        """List what pools this project has"""
        project = self._get_project_by_name(self._project_name)

        # Construct URL
        url = "/" + project.id + "/_apis/distributedtask/queues?actionFilter=16"

        #construct header parameters
        header_paramters = {}
        if self._user_mgr.is_msa_account():
            header_paramters['X-VSS-ForceMsaPassThrough'] = 'true'
        header_paramters['Accept'] = 'application/json'

        # Construct and send request
        request = self._client.get(url, headers=header_paramters)
        response = self._client.send(request)

        # Handle Response
        deserialized = None
        if response.status_code // 100 != 2:
            logging.error("GET %s", request.url)
            logging.error("response: %s", response.status_code)
            logging.error(response.text)
            raise HttpOperationError(self._deserialize, response)
        else:
            deserialized = self._deserialize('Pools', response)

        return deserialized

    def close_connection(self):
        self._client.close()
class BaseGithubManager(object):
    def __init__(self, base_url='https://api.github.com', pat=None):
        """Inits UserManager as to be able to send the right requests"""
        self._pat = pat
        self._config = Configuration(base_url=base_url)
        self._client = ServiceClient(None, self._config)

    def construct_github_request_header(self, pat=None):
        headers = {"Accept": "application/vnd.github.v3+json"}

        if pat:
            headers["Authorization"] = "token {pat}".format(pat=pat)
        elif self._pat:
            headers["Authorization"] = "token {pat}".format(pat=self._pat)

        return headers

    def close_connection(self):
        self._client.close()
Exemplo n.º 3
0
class UserManager(object):
    """ Get details about a user

    Attributes:
        See BaseManager
    """
    def __init__(self,
                 base_url='https://peprodscussu2.portalext.visualstudio.com',
                 creds=None):
        """Inits UserManager as to be able to send the right requests"""
        self._config = Configuration(base_url=base_url)
        self._client = ServiceClient(creds, self._config)
        #create the deserializer for the models
        client_models = {
            k: v
            for k, v in models.__dict__.items() if isinstance(v, type)
        }
        self._deserialize = Deserializer(client_models)

    def get_user_id(self, msa=False):
        """Get the user id"""

        header_parameters = {}
        if msa:
            header_parameters['X-VSS-ForceMsaPassThrough'] = 'true'
        header_parameters['Accept'] = 'application/json'
        request = self._client.get('/_apis/AzureTfs/UserContext')
        response = self._client.send(request, header_parameters)

        # Handle Response
        deserialized = None
        if response.status_code // 100 != 2:
            logging.error("GET %s", request.url)
            logging.error("response: %s", response.status_code)
            logging.error(response.text)
            raise HttpOperationError(self._deserialize, response)
        else:
            deserialized = self._deserialize('User', response)

        return deserialized

    def close_connection(self):
        self._client.close()
Exemplo n.º 4
0
class OrganizationManager():
    """ Manage DevOps organizations

    Create or list existing organizations

    Attributes:
        config: url configuration
        client: authentication client
        dserialize: deserializer to process http responses into python classes
    """
    def __init__(self,
                 base_url='https://app.vssps.visualstudio.com',
                 creds=None,
                 create_organization_url='https://app.vsaex.visualstudio.com'):
        """Inits OrganizationManager"""
        self._creds = creds
        self._config = Configuration(base_url=base_url)
        self._client = ServiceClient(creds, self._config)
        #need to make a secondary client for the creating organization as it uses a different base url
        self._create_organization_config = Configuration(
            base_url=create_organization_url)
        self._create_organization_client = ServiceClient(
            creds, self._create_organization_config)

        self._list_region_config = Configuration(
            base_url='https://aex.dev.azure.com')
        self._list_region_client = ServiceClient(
            creds, self._create_organization_config)
        client_models = {
            k: v
            for k, v in models.__dict__.items() if isinstance(v, type)
        }
        self._deserialize = Deserializer(client_models)

    def validate_organization_name(self, organization_name):
        """Validate an organization name by checking it does not already exist and that it fits name restrictions"""
        if organization_name is None:
            return models.ValidateAccountName(
                valid=False, message="The organization_name cannot be None")

        if re.search("[^0-9A-Za-z-]", organization_name):
            return models.ValidateAccountName(
                valid=False,
                message="""The name supplied contains forbidden characters.
                                                                      Only alphanumeric characters and dashes are allowed.
                                                                      Please try another organization name."""
            )
        #construct url
        url = '/_AzureSpsAccount/ValidateAccountName'

        #construct query parameters
        query_paramters = {}
        query_paramters['accountName'] = organization_name

        #construct header parameters
        header_paramters = {}
        header_paramters['Accept'] = 'application/json'

        request = self._client.get(url, params=query_paramters)
        response = self._client.send(request, headers=header_paramters)

        # Handle Response
        deserialized = None
        if response.status_code // 100 != 2:
            logging.error("GET %s", request.url)
            logging.error("response: %s", response.status_code)
            logging.error(response.text)
            raise HttpOperationError(self._deserialize, response)
        else:
            deserialized = self._deserialize('ValidateAccountName', response)

        return deserialized

    def list_organizations(self):
        """List what organizations this user is part of"""

        user_manager = UserManager(creds=self._creds)

        user_id_aad = user_manager.get_user_id(msa=False)
        user_id_msa = user_manager.get_user_id(msa=True)

        if (user_id_aad.id == user_id_msa.id):
            # Only need to do the one request as ids are the same
            organizations = self._list_organizations_request(user_id_aad.id)
        else:

            def uniq(lst):
                last = object()
                for item in lst:
                    if item == last:
                        continue
                    yield item
                    last = item

            # Need to do a request for each of the ids and then combine them
            organizations_aad = self._list_organizations_request(
                user_id_aad.id, msa=False)
            organizations_msa = self._list_organizations_request(
                user_id_msa.id, msa=True)
            organizations = organizations_aad
            # Now we just want to take the set of these two lists!
            organizations.value = list(
                uniq(organizations_aad.value + organizations_msa.value))
            organizations.count = len(organizations.value)

        return organizations

    def _list_organizations_request(self, member_id, msa=False):
        url = '/_apis/Commerce/Subscription'

        query_paramters = {}
        query_paramters['memberId'] = member_id
        query_paramters['includeMSAAccounts'] = True
        query_paramters['queryOnlyOwnerAccounts'] = True
        query_paramters['inlcudeDisabledAccounts'] = False
        query_paramters['providerNamespaceId'] = 'VisualStudioOnline'

        #construct header parameters
        header_parameters = {}
        if msa:
            header_parameters['X-VSS-ForceMsaPassThrough'] = 'true'
        header_parameters['Accept'] = 'application/json'

        request = self._client.get(url, params=query_paramters)
        response = self._client.send(request, headers=header_parameters)

        # Handle Response
        deserialized = None
        if response.status_code // 100 != 2:
            logging.error("GET %s", request.url)
            logging.error("response: %s", response.status_code)
            logging.error(response.text)
            raise HttpOperationError(self._deserialize, response)
        else:
            deserialized = self._deserialize('Organizations', response)

        return deserialized

    def create_organization(self, region_code, organization_name):
        """Create a new organization for user"""
        url = '/_apis/HostAcquisition/collections'

        #construct query parameters
        query_paramters = {}
        query_paramters['collectionName'] = organization_name
        query_paramters['preferredRegion'] = region_code
        query_paramters['api-version'] = '4.0-preview.1'

        #construct header parameters
        header_paramters = {}
        header_paramters['Accept'] = 'application/json'
        header_paramters['Content-Type'] = 'application/json'

        #construct the payload
        payload = {}
        payload[
            'VisualStudio.Services.HostResolution.UseCodexDomainForHostCreation'] = 'true'

        request = self._create_organization_client.post(url=url,
                                                        params=query_paramters,
                                                        content=payload)
        response = self._create_organization_client.send(
            request, headers=header_paramters)

        # Handle Response
        deserialized = None
        if response.status_code // 100 != 2:
            logging.error("GET %s", request.url)
            logging.error("response: %s", response.status_code)
            logging.error(response.text)
            raise HttpOperationError(self._deserialize, response)
        else:
            deserialized = self._deserialize('NewOrganization', response)

        return deserialized

    def list_regions(self):
        """List what regions organizations can exist in"""

        # Construct URL
        url = '/_apis/hostacquisition/regions'

        #construct header parameters
        header_paramters = {}
        header_paramters['Accept'] = 'application/json'

        # Construct and send request
        request = self._list_region_client.get(url, headers=header_paramters)
        response = self._list_region_client.send(request)

        # Handle Response
        deserialized = None
        if response.status_code // 100 != 2:
            logging.error("GET %s", request.url)
            logging.error("response: %s", response.status_code)
            logging.error(response.text)
            raise HttpOperationError(self._deserialize, response)
        else:
            deserialized = self._deserialize('Regions', response)

        return deserialized

    def close_connection(self):
        """Close the sessions"""
        self._client.close()
        self._create_organization_client.close()
Exemplo n.º 5
0
class UserManager(object):
    """ Get details about a user

    Attributes:
        See BaseManager
    """

    def __init__(self, base_url='https://peprodscussu2.portalext.visualstudio.com', creds=None):
        """Inits UserManager as to be able to send the right requests"""
        self._config = Configuration(base_url=base_url)
        self._client = ServiceClient(creds, self._config)
        #create the deserializer for the models
        client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
        self._deserialize = Deserializer(client_models)

        # create cache for two user type
        self._cache_aad_user = None
        self._cache_msa_user = None

    def is_msa_account(self):
        user_id_aad = self.get_user(msa=False).id
        user_id_msa = self.get_user(msa=True).id
        return user_id_aad != user_id_msa

    def get_user(self, msa=False):
        # Try to get from cache
        if msa is True and self._cache_msa_user is not None:
            return self._cache_msa_user
        if msa is False and self._cache_aad_user is not None:
            return self._cache_aad_user

        header_parameters = {}
        header_parameters['X-VSS-ForceMsaPassThrough'] = 'true' if msa else 'false'
        header_parameters['Accept'] = 'application/json'
        request = self._client.get('/_apis/AzureTfs/UserContext')
        response = self._client.send(request, header_parameters)

        # Handle Response
        deserialized = None
        if response.status_code // 100 != 2:
            logging.error("GET %s", request.url)
            logging.error("response: %s", response.status_code)
            logging.error(response.text)
            raise HttpOperationError(self._deserialize, response)
        else:
            deserialized = self._deserialize('User', response)

        # Write to cache
        if msa is True and self._cache_msa_user is None:
            self._cache_msa_user = deserialized
        if msa is False and self._cache_aad_user is None:
            self._cache_aad_user = deserialized

        return deserialized

    @property
    def aad_id(self):
        return self.get_user(msa=False).id

    @property
    def msa_id(self):
        return self.get_user(msa=True).id

    def close_connection(self):
        self._client.close()