Skip to content

Commit 9e928ee

Browse files
Merge pull request #63 from JaviCerveraIngram/CPS-36-directory-module
Added Directory class
2 parents 5034f88 + b354e82 commit 9e928ee

File tree

11 files changed

+441
-12
lines changed

11 files changed

+441
-12
lines changed

connect/resources/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# This file is part of the Ingram Micro Cloud Blue Connect SDK.
44
# Copyright (c) 2019 Ingram Micro. All Rights Reserved.
55

6+
from .directory import Directory
67
from .fulfillment_automation import FulfillmentAutomation
78
from .template import TemplateResource
89
from .tier_config_automation import TierConfigAutomation
@@ -11,6 +12,7 @@
1112

1213

1314
__all__ = [
15+
'Directory',
1416
'FulfillmentAutomation',
1517
'TemplateResource',
1618
'TierConfigAutomation',

connect/resources/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def get_url(self, path=''):
5555
def urljoin(*args):
5656
# type: (str) -> str
5757
return functools.reduce(
58-
lambda a, b: compat.urljoin(a + ('' if a.endswith('/') else '/'), b),
58+
lambda a, b: compat.urljoin(a + ('' if a.endswith('/') else '/'), b) if b else a,
5959
args)
6060

6161
@function_log

connect/resources/directory.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# This file is part of the Ingram Micro Cloud Blue Connect SDK.
4+
# Copyright (c) 2019 Ingram Micro. All Rights Reserved.
5+
6+
from connect.config import Config
7+
from connect.models import Asset, Product, TierConfig
8+
from connect.resources.base import ApiClient
9+
10+
11+
class Directory(object):
12+
""" Allows listing and obtaining several types of objects.
13+
14+
:param Config config: Config object or ``None`` to use environment config (default).
15+
"""
16+
17+
_config = None # type: Config
18+
19+
def __init__(self, config=None):
20+
self._config = config or Config.get_instance()
21+
22+
def list_assets(self, filters=None):
23+
""" List the assets.
24+
25+
:param (dict[str, Any] filters: Filters to pass to the request.
26+
:return: A list with the assets that match the given filters.
27+
:rtype: list[Asset]
28+
"""
29+
products = ','.join(self._config.products) if self._config.products else None
30+
url = self._config.api_url + 'assets?in(product.id,(' + products + '))' \
31+
if products \
32+
else 'assets'
33+
text, code = ApiClient(self._config, url).get(params=filters)
34+
return Asset.deserialize(text)
35+
36+
def get_asset(self, asset_id):
37+
""" Returns the asset with the given id.
38+
39+
:param str asset_id: The id of the asset.
40+
:return: The asset with the given id, or ``None`` if such asset does not exist.
41+
:rtype: Asset|None
42+
"""
43+
text, code = ApiClient(self._config, 'assets/' + asset_id).get()
44+
return Asset.deserialize(text)
45+
46+
def list_products(self):
47+
""" List the products. Filtering is not possible at the moment.
48+
49+
:return: A list with all products.
50+
:rtype: list[Product]
51+
"""
52+
text, code = ApiClient(self._config, 'products').get()
53+
return Product.deserialize(text)
54+
55+
def get_product(self, product_id):
56+
""" Returns the product with the given id.
57+
58+
:param str product_id: The id of the product.
59+
:return: The product with the given id, or ``None`` if such product does not exist.
60+
:rtype: Product|None
61+
"""
62+
text, code = ApiClient(self._config, 'products/' + product_id).get()
63+
return Product.deserialize(text)
64+
65+
def list_tier_configs(self, filters=None):
66+
""" List the tier configs.
67+
68+
:param (dict[str, Any] filters: Filters to pass to the request.
69+
:return: A list with the tier configs that match the given filters.
70+
:rtype: list[TierConfig]
71+
"""
72+
filters = filters or {}
73+
products_key = 'product.id'
74+
if products_key not in filters and self._config.products:
75+
filters[products_key] = ','.join(self._config.products)
76+
text, code = ApiClient(self._config, 'tier/configs').get(params=filters)
77+
return TierConfig.deserialize(text)
78+
79+
def get_tier_config(self, tier_config_id):
80+
""" Returns the tier config with the given id.
81+
82+
:param str tier_config_id: The id of the tier config.
83+
:return: The Tier Config with the given id, or ``None`` if such Tier Config does not exist.
84+
:rtype: TierConfig|None
85+
"""
86+
text, code = ApiClient(self._config, 'tier/configs/' + tier_config_id).get()
87+
return TierConfig.deserialize(text)

connect/resources/fulfillment_automation.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@ class FulfillmentAutomation(AutomationEngine):
3838
model_class = Fulfillment
3939

4040
def filters(self, status='pending', **kwargs):
41-
"""
42-
Returns the default set of filters for Fulfillment request, plus any others that you might
43-
specify. The allowed filters are:
41+
""" Returns the default set of filters for Fulfillment request, plus any others that you
42+
might specify. The allowed filters are:
4443
4544
- status
4645
- created

connect/resources/usage_automation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ class UsageAutomation(AutomationEngine):
2727
resource = 'listings'
2828
model_class = UsageFile
2929

30-
def filters(self, status='draft', **kwargs):
30+
def filters(self, status='listed', **kwargs):
3131
"""
32-
:param str status: Status of the requests. Default: ``'draft'``.
32+
:param str status: Status of the requests. Default: ``'listed'``.
3333
:param dict[str,Any] kwargs: Additional filters to add to the default ones.
3434
:return: The set of filters for this resource.
3535
:rtype: dict[str,Any]

tests/data/response_asset.json

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"id": "AS-9861-7949-8492",
3+
"status": "active",
4+
"events": {
5+
"created": {
6+
"at": "2018-06-04T13:19:10+00:00"
7+
},
8+
"updated": {
9+
"at": "2018-06-04T13:19:10+00:00"
10+
}
11+
},
12+
"external_id": "12345",
13+
"external_uid": "12435,518e10e8-3b1b-49b5-a480-b67675af4ae5",
14+
"external_name": "Fallball 498c84b1-d53318a6",
15+
"product": {
16+
"id": "CN-9861-7949-8492",
17+
"icon": "https://provider.connect.cloud.im/media/dapper-lynxes-35/mj301/media/mj301-logo.png",
18+
"name": "Fallball Awesome"
19+
},
20+
"connection": {
21+
"id": "CT-9861-7949-8492",
22+
"type": "production",
23+
"hub": {
24+
"id": "HB-12345-12345",
25+
"name": "Provider Production Hub",
26+
"account_id": "PA-9861-7949",
27+
"instance_id": "c106b775-7155-4b94-810d-a0c597fe801f"
28+
},
29+
"provider": {
30+
"name": "Ingram Micro Prod DA",
31+
"id": "PA-9861-7949"
32+
},
33+
"vendor": {
34+
"name": "Large Largo and Co",
35+
"id": "VA-9861-7949"
36+
}
37+
},
38+
"items": [
39+
{
40+
"id": "SKU-9861-7949-8492-0001",
41+
"mpn": "TEAM-ST3L2TAC1M",
42+
"quantity": "3"
43+
},
44+
{
45+
"id": "SKU-9861-7949-8492-0002",
46+
"mpn": "USR-FFFAC1M",
47+
"quantity": "1"
48+
}
49+
],
50+
"params": [
51+
{
52+
"id": "PM-9861-7949-8492-0001 #AUTOGEN #PRODUCT",
53+
"name": "Secondary email",
54+
"description": "This is a backup email for emergency",
55+
"type": "text",
56+
"value": "[email protected]"
57+
}
58+
],
59+
"tiers": {
60+
"customer": {
61+
"id": "TA-0-9861-7949-8492"
62+
},
63+
"tier1": {
64+
"id": "TA-1-9861-7949-8492"
65+
},
66+
"tier2": {
67+
"id": "TA-2-9861-7949-8492"
68+
}
69+
},
70+
"marketplace": {
71+
"id": "MP-12345",
72+
"name": "France and territories"
73+
},
74+
"contract": {
75+
"id": "CRP-00000-00000-00000",
76+
"name": "Contract of Program Agreement"
77+
}
78+
}

tests/data/response_product.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"id": "CN-783-317-575",
3+
"name": "Test Product",
4+
"icon": "https://provider.connect.cloud.im/media/dapper-lynxes-35/mj301/media/mj301-logo.png",
5+
"short_description": "",
6+
"detailed_description": "",
7+
"version": 2,
8+
"published_at": "2018-09-03T10:28:18.472670+00:00",
9+
"configurations": {
10+
"suspend_resume_supported": true,
11+
"requires_reseller_information": true
12+
},
13+
"customer_ui_settings": {
14+
"description": "description",
15+
"getting_started": "short description",
16+
"download_links": [
17+
{
18+
"title": "Windows",
19+
"url": "https://fallball.io/download/windows"
20+
},
21+
{
22+
"title": "macOS",
23+
"url": "https://fallball.io/download/macos"
24+
}
25+
],
26+
"documents": [
27+
{
28+
"title": "Admin Manual",
29+
"url": "https://fallball.io/manual/admin",
30+
"visible_for": "admin"
31+
},
32+
{
33+
"title": "User Manual",
34+
"url": "https://fallball.io/manual/user",
35+
"visible_for": "user"
36+
}
37+
],
38+
"languages": [
39+
{
40+
"id": "en_EN",
41+
"name": "English"
42+
},
43+
{
44+
"id": "de_DE",
45+
"name": "German"
46+
}
47+
]
48+
}
49+
}
50+
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"id": "TC-000-000-000",
3+
"name": "Configuration of Reseller",
4+
"account": {
5+
"id": "TA-1-000-000-000"
6+
},
7+
"product": {
8+
"id": "PRD-000-000-000",
9+
"icon": "https://provider.connect.cloud.im/media/dapper-lynxes-35/mj301/media/mj301-logo.png",
10+
"name": "Product"
11+
},
12+
"tier_level": 1,
13+
"connection": {
14+
"id": "CT-9861-7949-8492",
15+
"type": "production",
16+
"hub": {
17+
"id": "HB-12345-12345",
18+
"name": "Provider Production Hub"
19+
},
20+
"provider": {
21+
"name": "Ingram Micro Prod DA",
22+
"id": "PA-9861-7949"
23+
},
24+
"vendor": {
25+
"name": "Large Largo and Co",
26+
"id": "VA-9861-7949"
27+
}
28+
},
29+
"events": {
30+
"created": {
31+
"at": "2018-11-21T11:10:29+00:00"
32+
},
33+
"updated": {
34+
"at": "2018-11-21T11:10:29+00:00",
35+
"by": {
36+
"id": "PA-000-000",
37+
"name": "Username"
38+
}
39+
}
40+
},
41+
"params": [
42+
{
43+
"id": "param_a",
44+
"value": "param_a_value"
45+
}
46+
],
47+
"open_request": {
48+
"id": "TCR-000-000-000"
49+
},
50+
"template": {
51+
"id": "TP-000-000-000",
52+
"representation": "Render text is here......"
53+
},
54+
"contract": {
55+
"id": "CRD-00000-00000-00000",
56+
"name": "ACME Distribution Contract"
57+
},
58+
"marketplace": {
59+
"icon": "/media/PA-239-689/marketplaces/MP-54865/icon.png",
60+
"id": "MP-54865",
61+
"name": "Germany"
62+
}
63+
}

tests/test_conversation.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def test_add_message(post_mock):
5757
post_mock.assert_called_with(
5858
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
5959
json={'text': text},
60-
url='http://localhost:8080/api/public/v1/conversations/CO-750-033-356/messages/')
60+
url='http://localhost:8080/api/public/v1/conversations/CO-750-033-356/messages')
6161

6262
assert isinstance(message, ConversationMessage)
6363
assert message.id == 'ME-000-000-000'
@@ -85,7 +85,7 @@ def test_get_conversation_ok(get_mock):
8585
call(
8686
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
8787
params={'instance_id': request.id},
88-
url='http://localhost:8080/api/public/v1/conversations/'),
88+
url='http://localhost:8080/api/public/v1/conversations'),
8989
call(
9090
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
9191
url='http://localhost:8080/api/public/v1/conversations/' + conversation.id)
@@ -107,7 +107,7 @@ def test_get_conversation_empty(get_mock):
107107
call(
108108
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
109109
params={'instance_id': request.id},
110-
url='http://localhost:8080/api/public/v1/conversations/')
110+
url='http://localhost:8080/api/public/v1/conversations')
111111
])
112112

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

0 commit comments

Comments
 (0)