Skip to content

Commit

Permalink
Merge pull request #116 from cloudblue/various_improvements
Browse files Browse the repository at this point in the history
Various improvements
  • Loading branch information
marcserrat authored Sep 7, 2020
2 parents debddc3 + 192a06a commit 5d13803
Show file tree
Hide file tree
Showing 21 changed files with 204 additions and 32 deletions.
1 change: 1 addition & 0 deletions connect/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class ServerError(Exception):
"""

def __init__(self, error):
self.error = error
super(ServerError, self).__init__(str(error), error.error_code)


Expand Down
6 changes: 6 additions & 0 deletions connect/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .asset import Asset
from .base import BaseModel
from .billing import Billing
from .commitment import Commitment
from .company import Company
from .configuration import Configuration
from .connection import Connection
Expand Down Expand Up @@ -55,6 +56,8 @@
from .tier_account_request import TierAccountRequest
from .tier_config import TierConfig
from .tier_config_request import TierConfigRequest
from .ui import UI
from .unit import Unit
from .usage_file import UsageFile
from .usage_listing import UsageListing
from .usage_record import UsageRecord
Expand Down Expand Up @@ -83,6 +86,7 @@
'BillingRequest',
'Company',
'Configuration',
'Commitment',
'Connection',
'Constraints',
'Contact',
Expand Down Expand Up @@ -125,6 +129,8 @@
'TierAccounts',
'TierConfig',
'TierConfigRequest',
'UI',
'Unit',
'UsageFile',
'UsageListing',
'UsageRecord',
Expand Down
19 changes: 19 additions & 0 deletions connect/models/commitment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-

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

from .base import BaseModel
from .schemas import CommitmentSchema


class Commitment(BaseModel):
""" Billing commitment object. """

_schema = CommitmentSchema()

multiplier = None # type: str
""" (str) Commitment multiplier. """

count = None # type: int
""" (int) Number of commitments. """
12 changes: 12 additions & 0 deletions connect/models/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
from typing import List, Optional, Union

from .base import BaseModel
from .commitment import Commitment
from .param import Param
from .renewal import Renewal
from .schemas import ItemSchema
from .ui import UI
from .unit import Unit


class Item(BaseModel):
Expand Down Expand Up @@ -55,6 +58,15 @@ class Item(BaseModel):
name = None # type: str
""" (str) Name. """

unit = None # type: Unit
""" (Unit) Measure unit. """

commitment = None # type: Optional[Commitment]
""" (Commitment) item billing commitment. """

ui = None # type: UI
""" (UI) UI visibility. """

def get_param_by_id(self, param_id):
""" Get a parameter of the item.
Expand Down
41 changes: 39 additions & 2 deletions connect/models/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@


class BaseSchema(Schema):

def __init__(self, *args, **kwargs):
# kwargs['strict'] = True
super(BaseSchema, self).__init__(*args, **kwargs)

id = fields.Str()

# Set allow_none to True in all fields
Expand Down Expand Up @@ -334,18 +339,50 @@ def make_object(self, data):
return Param(**data)


class UISchema(BaseSchema):
visibility = fields.Bool()
@post_load
def make_object(self, data):
from connect.models import UI
return UI(**data)


class UnitSchema(BaseSchema):
title = fields.Str()
unit = fields.Str()

@post_load
def make_object(self, data):
from connect.models import Unit
return Unit(**data)


class CommitmentSchema(BaseSchema):
multiplier = fields.Str()
count = fields.Int()

@post_load
def make_object(self, data):
from connect.models import Commitment
return Commitment(**data)


class ItemSchema(BaseSchema):
mpn = fields.Str()
quantity = QuantityField()
old_quantity = QuantityField()
renewal = fields.Nested(RenewalSchema)
unit = fields.Nested(UnitSchema)
commitment = fields.Nested(CommitmentSchema)
params = fields.Nested(ParamSchema, many=True)
display_name = fields.Str()
global_id = fields.Str()
item_type = fields.Str()
description = fields.Str()
period = fields.Str()
type = fields.Str()
name = fields.Str()
ui = fields.Nested(UISchema)

@post_load
def make_object(self, data):
Expand Down Expand Up @@ -828,8 +865,8 @@ def make_object(self, data):


class AttributesSchema(BaseSchema):
provider = fields.Nested(CompanySchema, only=('external_id'))
vendor = fields.Nested(CompanySchema, only=('external_id'))
provider = fields.Nested(CompanySchema, only=('external_id',))
vendor = fields.Nested(CompanySchema, only=('external_id',))

@post_load
def make_object(self, data):
Expand Down
16 changes: 16 additions & 0 deletions connect/models/ui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-

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

from .base import BaseModel
from .schemas import UISchema


class UI(BaseModel):
""" UI object. """

_schema = UISchema()

visibility = None # type: bool
""" (str) Item UI visibility. """
19 changes: 19 additions & 0 deletions connect/models/unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-

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

from .base import BaseModel
from .schemas import UnitSchema


class Unit(BaseModel):
""" Unit object. """

_schema = UnitSchema()

title = None # type: str
""" (str) Name of measure unit. """

unit = None # type: str
""" (str) unit code of measure unit. """
26 changes: 20 additions & 6 deletions connect/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,11 @@ class BaseResource(object):

def __init__(self, config=None):
# Set client
if not self.__class__.resource:
if not self.resource:
raise AttributeError('Resource name not specified in class {}. '
'Add an attribute `resource` with the name of the resource'
.format(self.__class__.__name__))
self._api = ApiClient(config, self.__class__.resource)
self._api = ApiClient(config, self.resource)

@property
def config(self):
Expand All @@ -161,12 +161,15 @@ def get(self, pk):

def filters(self, **kwargs):
# type: (Dict[str, Any]) -> Dict[str, Any]
filters = {}
query = Query()
if self.limit:
filters['limit'] = self.limit
query = query.limit(self.limit)
for key, val in kwargs.items():
filters[key] = val
return filters
if isinstance(val, (list, tuple)):
query = query.in_(key, val)
else:
query = query.equal(key, val)
return query

@function_log
def search(self, filters=None):
Expand Down Expand Up @@ -208,3 +211,14 @@ def update(self, id_obj, body):

def list(self, filters=None):
return self.search(filters)


class NestedResource(BaseResource):
"""Base class for all nested resources"""

def __init__(self, config=None, parent_path=''):
self.resource = '{}/{}'.format(
parent_path,
self.__class__.resource,
)
super(NestedResource, self).__init__(config)
6 changes: 3 additions & 3 deletions connect/resources/fulfillment_automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ def filters(self, status='pending', **kwargs):
:return: The set of filters for this resource.
:rtype: dict[str,Any]
"""
filters = super(FulfillmentAutomation, self).filters(status=status, **kwargs)
query = super(FulfillmentAutomation, self).filters(status=status, **kwargs)
if self.config.products:
filters['asset.product.id__in'] = ','.join(self.config.products)
return filters
query.in_('asset.product.id', self.config.products)
return query

@function_log
def dispatch(self, request):
Expand Down
14 changes: 13 additions & 1 deletion connect/resources/product.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import json
from .base import BaseResource

from .base import BaseResource, NestedResource
from ..models import Product, Item


class ProductItemResource(NestedResource):
resource = 'items'
model_class = Item


class ProductsResource(BaseResource):
""" Allows listing and obtaining several types of objects.
:param Config config: Config object or ``None`` to use environment config (default).
"""
resource = 'products'
model_class = Product

def list_parameters(self, product_id):
""" List parameters for a product.
Expand Down Expand Up @@ -75,3 +83,7 @@ def delete_parameter(self, product_id, parameter_id):
path=path
)
return response

def items(self, product_id):
"""Returns the ProductItemResource resource"""
return ProductItemResource(self.config, 'products/{}'.format(product_id))
6 changes: 3 additions & 3 deletions connect/resources/tier_config_automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ def filters(self, status='pending', **kwargs):
:return: The set of filters for this resource.
:rtype: dict[str,Any]
"""
filters = super(TierConfigAutomation, self).filters(status=status, **kwargs)
query = super(TierConfigAutomation, self).filters(status=status, **kwargs)
if self.config.products:
filters['configuration.product.id'] = ','.join(self.config.products)
return filters
query.in_('configuration.product.id', self.config.products)
return query

@function_log
def dispatch(self, request):
Expand Down
6 changes: 3 additions & 3 deletions connect/resources/usage_automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ def filters(self, status='listed', **kwargs):
:return: The set of filters for this resource.
:rtype: dict[str,Any]
"""
filters = super(UsageAutomation, self).filters(status, **kwargs)
query = super(UsageAutomation, self).filters(status, **kwargs)
if self.config.products:
filters['product__id'] = ','.join(self.config.products)
return filters
query.in_('product.id', self.config.products)
return query

def dispatch(self, request):
# type: (UsageListing) -> str
Expand Down
6 changes: 3 additions & 3 deletions connect/resources/usage_file_automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ def filters(self, status='ready', **kwargs):
:return: The set of filters for this resource.
:rtype: dict[str,Any]
"""
filters = super(UsageFileAutomation, self).filters(status, **kwargs)
query = super(UsageFileAutomation, self).filters(status, **kwargs)
if self.config.products:
filters['product_id'] = ','.join(self.config.products)
return filters
query.in_('product_id', self.config.products)
return query

def dispatch(self, request):
# type: (UsageFile) -> str
Expand Down
2 changes: 1 addition & 1 deletion requirements/sdk.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
deprecation==2.0.6
marshmallow==2.18.0
openpyxl==2.5.14
openpyxl>=2.5.14
requests==2.21.0
six==1.12.0
pathlib==1.0.1
Expand Down
3 changes: 1 addition & 2 deletions tests/test_billing_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,8 @@ def test_list_billing_request_ok(self, get_mock):
get_mock.assert_has_calls([
call(
headers={'Authorization': 'ApiKey XXXX:YYYYY', 'Content-Type': 'application/json'},
params={'limit': 100},
timeout=300,
url='http://localhost:8080/api/public/v1/subscriptions/requests')
url='http://localhost:8080/api/public/v1/subscriptions/requests?limit=100')
])
self.assertEqual(len(billing_request), 2, msg=None)

Expand Down
3 changes: 1 addition & 2 deletions tests/test_directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,8 @@ def test_list_marketplaces(get_mock):
assert marketplaces[0].id == 'MP-12345'

get_mock.assert_called_with(
url='http://localhost:8080/api/public/v1/marketplaces',
url='http://localhost:8080/api/public/v1/marketplaces?limit=100',
headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
params={'limit': 100},
timeout=300)


Expand Down
Loading

0 comments on commit 5d13803

Please sign in to comment.