Skip to content
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: 2 additions & 0 deletions connect/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# This file is part of the Ingram Micro Cloud Blue Connect SDK.
# Copyright (c) 2019 Ingram Micro. All Rights Reserved.

from .directory import Directory
from .fulfillment_automation import FulfillmentAutomation
from .template import TemplateResource
from .tier_config_automation import TierConfigAutomation
Expand All @@ -11,6 +12,7 @@


__all__ = [
'Directory',
'FulfillmentAutomation',
'TemplateResource',
'TierConfigAutomation',
Expand Down
2 changes: 1 addition & 1 deletion connect/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def get_url(self, path=''):
def urljoin(*args):
# type: (str) -> str
return functools.reduce(
lambda a, b: compat.urljoin(a + ('' if a.endswith('/') else '/'), b),
lambda a, b: compat.urljoin(a + ('' if a.endswith('/') else '/'), b) if b else a,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been added to avoid the URL having an additional trailing slash.

args)

@function_log
Expand Down
87 changes: 87 additions & 0 deletions connect/resources/directory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-

# This file is part of the Ingram Micro Cloud Blue Connect SDK.
# Copyright (c) 2019 Ingram Micro. All Rights Reserved.

from connect.config import Config
from connect.models import Asset, Product, TierConfig
from connect.resources.base import ApiClient


class Directory(object):
""" Allows listing and obtaining several types of objects.

:param Config config: Config object or ``None`` to use environment config (default).
"""

_config = None # type: Config

def __init__(self, config=None):
self._config = config or Config.get_instance()

def list_assets(self, filters=None):
""" List the assets.

:param (dict[str, Any] filters: Filters to pass to the request.
:return: A list with the assets that match the given filters.
:rtype: list[Asset]
"""
products = ','.join(self._config.products) if self._config.products else None
url = self._config.api_url + 'assets?in(product.id,(' + products + '))' \
if products \
else 'assets'
text, code = ApiClient(self._config, url).get(params=filters)
return Asset.deserialize(text)

def get_asset(self, asset_id):
""" Returns the asset with the given id.

:param str asset_id: The id of the asset.
:return: The asset with the given id, or ``None`` if such asset does not exist.
:rtype: Asset|None
"""
text, code = ApiClient(self._config, 'assets/' + asset_id).get()
return Asset.deserialize(text)

def list_products(self):
""" List the products. Filtering is not possible at the moment.

:return: A list with all products.
:rtype: list[Product]
"""
text, code = ApiClient(self._config, 'products').get()
return Product.deserialize(text)

def get_product(self, product_id):
""" Returns the product with the given id.

:param str product_id: The id of the product.
:return: The product with the given id, or ``None`` if such product does not exist.
:rtype: Product|None
"""
text, code = ApiClient(self._config, 'products/' + product_id).get()
return Product.deserialize(text)

def list_tier_configs(self, filters=None):
""" List the tier configs.

:param (dict[str, Any] filters: Filters to pass to the request.
:return: A list with the tier configs that match the given filters.
:rtype: list[TierConfig]
"""
filters = filters or {}
products_key = 'product.id'
if products_key not in filters and self._config.products:
filters[products_key] = ','.join(self._config.products)
text, code = ApiClient(self._config, 'tier/configs').get(params=filters)
return TierConfig.deserialize(text)

def get_tier_config(self, tier_config_id):
""" Returns the tier config with the given id.

:param str tier_config_id: The id of the tier config.
:return: The Tier Config with the given id, or ``None`` if such Tier Config does not exist.
:rtype: TierConfig|None
"""
text, code = ApiClient(self._config, 'tier/configs/' + tier_config_id).get()
return TierConfig.deserialize(text)
5 changes: 2 additions & 3 deletions connect/resources/fulfillment_automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ class FulfillmentAutomation(AutomationEngine):
model_class = Fulfillment

def filters(self, status='pending', **kwargs):
"""
Returns the default set of filters for Fulfillment request, plus any others that you might
specify. The allowed filters are:
""" Returns the default set of filters for Fulfillment request, plus any others that you
might specify. The allowed filters are:

- status
- created
Expand Down
4 changes: 2 additions & 2 deletions connect/resources/usage_automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ class UsageAutomation(AutomationEngine):
resource = 'listings'
model_class = UsageFile

def filters(self, status='draft', **kwargs):
def filters(self, status='listed', **kwargs):
"""
:param str status: Status of the requests. Default: ``'draft'``.
:param str status: Status of the requests. Default: ``'listed'``.
:param dict[str,Any] kwargs: Additional filters to add to the default ones.
:return: The set of filters for this resource.
:rtype: dict[str,Any]
Expand Down
78 changes: 78 additions & 0 deletions tests/data/response_asset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"id": "AS-9861-7949-8492",
"status": "active",
"events": {
"created": {
"at": "2018-06-04T13:19:10+00:00"
},
"updated": {
"at": "2018-06-04T13:19:10+00:00"
}
},
"external_id": "12345",
"external_uid": "12435,518e10e8-3b1b-49b5-a480-b67675af4ae5",
"external_name": "Fallball 498c84b1-d53318a6",
"product": {
"id": "CN-9861-7949-8492",
"icon": "https://provider.connect.cloud.im/media/dapper-lynxes-35/mj301/media/mj301-logo.png",
"name": "Fallball Awesome"
},
"connection": {
"id": "CT-9861-7949-8492",
"type": "production",
"hub": {
"id": "HB-12345-12345",
"name": "Provider Production Hub",
"account_id": "PA-9861-7949",
"instance_id": "c106b775-7155-4b94-810d-a0c597fe801f"
},
"provider": {
"name": "Ingram Micro Prod DA",
"id": "PA-9861-7949"
},
"vendor": {
"name": "Large Largo and Co",
"id": "VA-9861-7949"
}
},
"items": [
{
"id": "SKU-9861-7949-8492-0001",
"mpn": "TEAM-ST3L2TAC1M",
"quantity": "3"
},
{
"id": "SKU-9861-7949-8492-0002",
"mpn": "USR-FFFAC1M",
"quantity": "1"
}
],
"params": [
{
"id": "PM-9861-7949-8492-0001 #AUTOGEN #PRODUCT",
"name": "Secondary email",
"description": "This is a backup email for emergency",
"type": "text",
"value": "daniel.lark@gmail.com"
}
],
"tiers": {
"customer": {
"id": "TA-0-9861-7949-8492"
},
"tier1": {
"id": "TA-1-9861-7949-8492"
},
"tier2": {
"id": "TA-2-9861-7949-8492"
}
},
"marketplace": {
"id": "MP-12345",
"name": "France and territories"
},
"contract": {
"id": "CRP-00000-00000-00000",
"name": "Contract of Program Agreement"
}
}
50 changes: 50 additions & 0 deletions tests/data/response_product.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"id": "CN-783-317-575",
"name": "Test Product",
"icon": "https://provider.connect.cloud.im/media/dapper-lynxes-35/mj301/media/mj301-logo.png",
"short_description": "",
"detailed_description": "",
"version": 2,
"published_at": "2018-09-03T10:28:18.472670+00:00",
"configurations": {
"suspend_resume_supported": true,
"requires_reseller_information": true
},
"customer_ui_settings": {
"description": "description",
"getting_started": "short description",
"download_links": [
{
"title": "Windows",
"url": "https://fallball.io/download/windows"
},
{
"title": "macOS",
"url": "https://fallball.io/download/macos"
}
],
"documents": [
{
"title": "Admin Manual",
"url": "https://fallball.io/manual/admin",
"visible_for": "admin"
},
{
"title": "User Manual",
"url": "https://fallball.io/manual/user",
"visible_for": "user"
}
],
"languages": [
{
"id": "en_EN",
"name": "English"
},
{
"id": "de_DE",
"name": "German"
}
]
}
}

63 changes: 63 additions & 0 deletions tests/data/response_tier_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"id": "TC-000-000-000",
"name": "Configuration of Reseller",
"account": {
"id": "TA-1-000-000-000"
},
"product": {
"id": "PRD-000-000-000",
"icon": "https://provider.connect.cloud.im/media/dapper-lynxes-35/mj301/media/mj301-logo.png",
"name": "Product"
},
"tier_level": 1,
"connection": {
"id": "CT-9861-7949-8492",
"type": "production",
"hub": {
"id": "HB-12345-12345",
"name": "Provider Production Hub"
},
"provider": {
"name": "Ingram Micro Prod DA",
"id": "PA-9861-7949"
},
"vendor": {
"name": "Large Largo and Co",
"id": "VA-9861-7949"
}
},
"events": {
"created": {
"at": "2018-11-21T11:10:29+00:00"
},
"updated": {
"at": "2018-11-21T11:10:29+00:00",
"by": {
"id": "PA-000-000",
"name": "Username"
}
}
},
"params": [
{
"id": "param_a",
"value": "param_a_value"
}
],
"open_request": {
"id": "TCR-000-000-000"
},
"template": {
"id": "TP-000-000-000",
"representation": "Render text is here......"
},
"contract": {
"id": "CRD-00000-00000-00000",
"name": "ACME Distribution Contract"
},
"marketplace": {
"icon": "/media/PA-239-689/marketplaces/MP-54865/icon.png",
"id": "MP-54865",
"name": "Germany"
}
}
8 changes: 4 additions & 4 deletions tests/test_conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_add_message(post_mock):
post_mock.assert_called_with(
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
json={'text': text},
url='http://localhost:8080/api/public/v1/conversations/CO-750-033-356/messages/')
url='http://localhost:8080/api/public/v1/conversations/CO-750-033-356/messages')

assert isinstance(message, ConversationMessage)
assert message.id == 'ME-000-000-000'
Expand Down Expand Up @@ -85,7 +85,7 @@ def test_get_conversation_ok(get_mock):
call(
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
params={'instance_id': request.id},
url='http://localhost:8080/api/public/v1/conversations/'),
url='http://localhost:8080/api/public/v1/conversations'),
call(
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
url='http://localhost:8080/api/public/v1/conversations/' + conversation.id)
Expand All @@ -107,7 +107,7 @@ def test_get_conversation_empty(get_mock):
call(
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
params={'instance_id': request.id},
url='http://localhost:8080/api/public/v1/conversations/')
url='http://localhost:8080/api/public/v1/conversations')
])

assert conversation is None
Expand All @@ -129,7 +129,7 @@ def test_get_conversation_bad_deserialize(get_mock):
call(
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
params={'instance_id': request.id},
url='http://localhost:8080/api/public/v1/conversations/'),
url='http://localhost:8080/api/public/v1/conversations'),
call(
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
url='http://localhost:8080/api/public/v1/conversations/CO-750-033-356')
Expand Down
Loading