Skip to content

Commit 8f3db4a

Browse files
authored
Merge pull request #28 from cloudblue/LITE-20681-new-events-types
New event types
2 parents f8ba95a + 3e21310 commit 8f3db4a

28 files changed

+2798
-1244
lines changed

connect/eaas/config.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#
2+
# This file is part of the Ingram Micro CloudBlue Connect EaaS Extension Runner.
3+
#
4+
# Copyright (c) 2021 Ingram Micro. All Rights Reserved.
5+
#
6+
import logging
7+
8+
from connect.eaas.helpers import (
9+
get_environment,
10+
)
11+
12+
13+
logger = logging.getLogger(__name__)
14+
15+
16+
class ConfigHelper:
17+
"""
18+
Provides both static (from env vars) and dynamic (from backend)
19+
configuration.
20+
"""
21+
def __init__(self, secure=True):
22+
self.secure = secure
23+
self.env = get_environment()
24+
self.dyn_config = None
25+
26+
@property
27+
def api_key(self):
28+
return self.env['api_key']
29+
30+
@property
31+
def service_id(self):
32+
return self.dyn_config.service_id
33+
34+
@property
35+
def product_id(self):
36+
return self.dyn_config.product_id
37+
38+
@property
39+
def hub_id(self):
40+
return self.dyn_config.hub_id
41+
42+
@property
43+
def environment_id(self):
44+
return self.env['environment_id']
45+
46+
@property
47+
def instance_id(self):
48+
return self.env['instance_id']
49+
50+
@property
51+
def environment_type(self):
52+
return self.dyn_config.environment_type
53+
54+
@property
55+
def account_id(self):
56+
return self.dyn_config.account_id
57+
58+
@property
59+
def account_name(self):
60+
return self.dyn_config.account_name
61+
62+
@property
63+
def logging_api_key(self):
64+
return self.dyn_config.logging_api_key
65+
66+
@property
67+
def variables(self):
68+
return self.dyn_config.configuration
69+
70+
@property
71+
def metadata(self):
72+
return {
73+
'api_address': self.env['api_address'],
74+
'service_id': self.service_id,
75+
'environment_id': self.environment_id,
76+
'environment_type': self.environment_type,
77+
'instance_id': self.instance_id,
78+
'account_id': self.account_id,
79+
'account_name': self.account_name,
80+
}
81+
82+
def get_ws_url(self):
83+
proto = 'wss' if self.secure else 'ws'
84+
return (
85+
f'{proto}://{self.env["ws_address"]}/public/v1/devops/ws'
86+
f'/{self.env["environment_id"]}/{self.env["instance_id"]}'
87+
)
88+
89+
def get_api_url(self):
90+
return f'https://{self.env["api_address"]}/public/v1'
91+
92+
def get_headers(self):
93+
return (('Authorization', self.api_key),)
94+
95+
def get_timeout(self, category):
96+
return self.env[f'{category}_task_max_execution_time']
97+
98+
def update_dynamic_config(self, data):
99+
"""Updates the dynamic configuration."""
100+
self.dyn_config = data
101+
logger.info(f'Runner dynamic config updated {data}')
102+
if data.log_level:
103+
logger.info(f'Change extesion logger level to {data.log_level}')
104+
logging.getLogger('eaas.extension').setLevel(
105+
getattr(logging, data.log_level),
106+
)
107+
if data.runner_log_level:
108+
logging.getLogger('connect.eaas').setLevel(
109+
getattr(logging, data.runner_log_level),
110+
)

connect/eaas/constants.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
TaskType.TIER_CONFIG_ADJUSTMENT_REQUEST_PROCESSING: 'process_tier_config_adjustment_request',
2424
TaskType.TIER_CONFIG_SETUP_REQUEST_VALIDATION: 'validate_tier_config_setup_request',
2525
TaskType.TIER_CONFIG_CHANGE_REQUEST_VALIDATION: 'validate_tier_config_change_request',
26+
TaskType.LISTING_NEW_REQUEST_PROCESSING: 'process_new_listing_request',
27+
TaskType.LISTING_REMOVE_REQUEST_PROCESSING: 'process_remove_listing_request',
28+
TaskType.TIER_ACCOUNT_UPDATE_REQUEST_PROCESSING: 'process_tier_account_update_request',
29+
TaskType.USAGE_FILE_REQUEST_PROCESSING: 'process_usage_file',
30+
TaskType.PART_USAGE_FILE_REQUEST_PROCESSING: 'process_usage_chunk_file',
2631
}
2732

2833
ASSET_REQUEST_TASK_TYPES = (
@@ -44,6 +49,11 @@
4449
TaskType.TIER_CONFIG_ADJUSTMENT_REQUEST_PROCESSING,
4550
)
4651

52+
LISTING_REQUEST_TASK_TYPES = (
53+
TaskType.LISTING_NEW_REQUEST_PROCESSING,
54+
TaskType.LISTING_REMOVE_REQUEST_PROCESSING,
55+
)
56+
4757
BACKGROUND_TASK_TYPES = (
4858
TaskType.ASSET_PURCHASE_REQUEST_PROCESSING,
4959
TaskType.ASSET_CHANGE_REQUEST_PROCESSING,
@@ -54,6 +64,12 @@
5464
TaskType.TIER_CONFIG_SETUP_REQUEST_PROCESSING,
5565
TaskType.TIER_CONFIG_CHANGE_REQUEST_PROCESSING,
5666
TaskType.TIER_CONFIG_ADJUSTMENT_REQUEST_PROCESSING,
67+
TaskType.LISTING_NEW_REQUEST_PROCESSING,
68+
TaskType.LISTING_REMOVE_REQUEST_PROCESSING,
69+
TaskType.TIER_ACCOUNT_UPDATE_REQUEST_PROCESSING,
70+
TaskType.USAGE_FILE_REQUEST_PROCESSING,
71+
TaskType.PART_USAGE_FILE_REQUEST_PROCESSING,
72+
5773
)
5874

5975
INTERACTIVE_TASK_TYPES = (
@@ -65,7 +81,19 @@
6581
TaskType.PRODUCT_CUSTOM_EVENT_PROCESSING,
6682
)
6783

84+
VALIDATION_TASK_TYPES = (
85+
TaskType.ASSET_PURCHASE_REQUEST_VALIDATION,
86+
TaskType.ASSET_CHANGE_REQUEST_VALIDATION,
87+
TaskType.TIER_CONFIG_SETUP_REQUEST_VALIDATION,
88+
TaskType.TIER_CONFIG_CHANGE_REQUEST_VALIDATION,
89+
)
90+
91+
OTHER_INTERACTIVE_TASK_TYPES = (
92+
TaskType.PRODUCT_ACTION_EXECUTION,
93+
TaskType.PRODUCT_CUSTOM_EVENT_PROCESSING,
94+
)
95+
6896
BACKGROUND_TASK_MAX_EXECUTION_TIME = 300
6997
INTERACTIVE_TASK_MAX_EXECUTION_TIME = 120
70-
SCHEDULED_TASK_MAX_EXECUTION_TIME = 300
98+
SCHEDULED_TASK_MAX_EXECUTION_TIME = 60 * 60 * 12
7199
RESULT_SENDER_MAX_RETRIES = 5

connect/eaas/dataclasses.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ class TaskType:
1919
TIER_CONFIG_SETUP_REQUEST_VALIDATION = 'tier_config_setup_request_validation'
2020
TIER_CONFIG_CHANGE_REQUEST_VALIDATION = 'tier_config_change_request_validation'
2121
SCHEDULED_EXECUTION = 'scheduled_execution'
22+
LISTING_NEW_REQUEST_PROCESSING = 'listing_new_request_processing'
23+
LISTING_REMOVE_REQUEST_PROCESSING = 'listing_remove_request_processing'
24+
TIER_ACCOUNT_UPDATE_REQUEST_PROCESSING = 'tier_account_update_request_processing'
25+
USAGE_FILE_REQUEST_PROCESSING = 'usage_file_request_processing'
26+
PART_USAGE_FILE_REQUEST_PROCESSING = 'part_usage_file_request_processing'
2227

2328

2429
class MessageType:
@@ -68,6 +73,8 @@ class ConfigurationPayload:
6873
service_id: Optional[str] = None
6974
log_level: Optional[str] = None
7075
runner_log_level: Optional[str] = None
76+
product_id: Optional[str] = None
77+
hub_id: Optional[str] = None
7178

7279

7380
@dataclasses.dataclass

connect/eaas/extension.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def __init__(self, client, logger, config):
116116
self.config = config
117117

118118
@classmethod
119-
def get_descriptor(cls):
119+
def get_descriptor(cls): # pragma: no cover
120120
return json.load(
121121
pkg_resources.resource_stream(
122122
cls.__module__,
@@ -168,3 +168,18 @@ def execute_product_action(self, request): # pragma: no cover
168168

169169
def process_product_custom_event(self, request): # pragma: no cover
170170
raise NotImplementedError()
171+
172+
def process_new_listing_request(self, request): # pragma: no cover
173+
raise NotImplementedError()
174+
175+
def process_remove_listing_request(self, request): # pragma: no cover
176+
raise NotImplementedError()
177+
178+
def process_tier_account_update_request(self, request): # pragma: no cover
179+
raise NotImplementedError()
180+
181+
def process_usage_file(self, request): # pragma: no cover
182+
raise NotImplementedError()
183+
184+
def process_usage_chunk_file(self, request): # pragma: no cover
185+
raise NotImplementedError()

connect/eaas/handler.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import logging
2+
3+
from connect.client import AsyncConnectClient, ConnectClient
4+
from connect.eaas.helpers import (
5+
get_extension_class,
6+
get_extension_type,
7+
)
8+
from connect.eaas.config import ConfigHelper
9+
from connect.eaas.logging import ExtensionLogHandler, RequestLogger
10+
11+
12+
class ExtensionHandler:
13+
"""
14+
Handle the lifecycle of an extension.
15+
"""
16+
def __init__(self, config: ConfigHelper):
17+
self.config = config
18+
self.extension_class = get_extension_class()
19+
self.extension_type = get_extension_type(self.extension_class)
20+
self.descriptor = self.extension_class.get_descriptor()
21+
self.logging_handler = None
22+
23+
@property
24+
def capabilities(self):
25+
return self.descriptor['capabilities']
26+
27+
@property
28+
def variables(self):
29+
return self.descriptor.get('variables')
30+
31+
@property
32+
def schedulables(self):
33+
return self.descriptor.get('schedulables')
34+
35+
@property
36+
def readme(self):
37+
return self.descriptor['readme_url']
38+
39+
@property
40+
def changelog(self):
41+
return self.descriptor['changelog_url']
42+
43+
def new_extension(self, task_id):
44+
return self.extension_class(
45+
self._create_client(task_id),
46+
logging.LoggerAdapter(
47+
self._create_logger(),
48+
{'task_id': task_id},
49+
),
50+
self.config.variables,
51+
)
52+
53+
def _create_logger(self):
54+
"""
55+
Returns a logger instance configured with the LogZ.io handler.
56+
This logger will be used by the extension to send logging records
57+
to the Logz.io service.
58+
"""
59+
logger = logging.getLogger('eaas.extension')
60+
if self.logging_handler is None and self.config.logging_api_key is not None:
61+
self.logging_handler = ExtensionLogHandler(
62+
self.config.logging_api_key,
63+
default_extra_fields=self.config.metadata,
64+
)
65+
logger.addHandler(self.logging_handler)
66+
return logger
67+
68+
def _create_client(self, task_id):
69+
"""
70+
Get an instance of the Connect Openapi Client. If the extension is asyncrhonous
71+
it returns an instance of the AsyncConnectClient otherwise the ConnectClient.
72+
"""
73+
Client = ConnectClient if self.extension_type == 'sync' else AsyncConnectClient
74+
return Client(
75+
self.config.api_key,
76+
endpoint=self.config.get_api_url(),
77+
use_specs=False,
78+
logger=RequestLogger(
79+
logging.LoggerAdapter(
80+
self._create_logger(),
81+
{'task_id': task_id},
82+
),
83+
),
84+
)

connect/eaas/helpers.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010

1111
import pkg_resources
1212

13-
from connect.eaas.constants import TASK_TYPE_EXT_METHOD_MAP
13+
from connect.eaas.constants import (
14+
BACKGROUND_TASK_MAX_EXECUTION_TIME,
15+
INTERACTIVE_TASK_MAX_EXECUTION_TIME,
16+
SCHEDULED_TASK_MAX_EXECUTION_TIME,
17+
TASK_TYPE_EXT_METHOD_MAP,
18+
)
1419
from connect.eaas.exceptions import EaaSError
1520

1621

@@ -57,6 +62,15 @@ def get_environment():
5762
'instance_id': os.getenv('INSTANCE_ID', get_container_id()),
5863
'ws_address': os.getenv('SERVER_ADDRESS', 'api.cnct.info'),
5964
'api_address': os.getenv('API_ADDRESS', os.getenv('SERVER_ADDRESS', 'api.cnct.info')),
65+
'background_task_max_execution_time': int(os.getenv(
66+
'BACKGROUND_TASK_MAX_EXECUTION_TIME', BACKGROUND_TASK_MAX_EXECUTION_TIME,
67+
)),
68+
'interactive_task_max_execution_time': int(os.getenv(
69+
'INTERACTIVE_TASK_MAX_EXECUTION_TIME', INTERACTIVE_TASK_MAX_EXECUTION_TIME,
70+
)),
71+
'scheduled_task_max_execution_time': int(os.getenv(
72+
'SCHEDULED_TASK_MAX_EXECUTION_TIME', SCHEDULED_TASK_MAX_EXECUTION_TIME,
73+
)),
6074
}
6175

6276

connect/eaas/logging.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ def extra_fields(self, message):
1515

1616

1717
class RequestLogger:
18-
1918
def __init__(self, logger):
2019
self.logger = logger
2120

0 commit comments

Comments
 (0)