Skip to content

Commit

Permalink
Merge pull request #144 from SUSE-Enceladus/impl-archive
Browse files Browse the repository at this point in the history
Implement archive record function
  • Loading branch information
smarlowucf authored Jan 10, 2024
2 parents f342b84 + 7718fa6 commit f946719
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 1 deletion.
2 changes: 2 additions & 0 deletions csp_billing_adapter/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
csp_hookspecs,
hookspecs,
storage_hookspecs,
archive_hookspecs,
hookimpls
)

Expand All @@ -71,6 +72,7 @@ def get_plugin_manager() -> pluggy.PluginManager:
pm.add_hookspecs(hookspecs)
pm.add_hookspecs(csp_hookspecs)
pm.add_hookspecs(storage_hookspecs)
pm.add_hookspecs(archive_hookspecs)
pm.register(hookimpls)
pm.load_setuptools_entrypoints('csp_billing_adapter')
return pm
Expand Down
55 changes: 55 additions & 0 deletions csp_billing_adapter/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@

"""Utility functions for handling a rolling dictionary archive."""

import functools
import logging

from csp_billing_adapter.config import Config
from csp_billing_adapter.utils import retry_on_exception

log = logging.getLogger('CSPBillingAdapter')

DEFAULT_RETENTION_PERIOD = 6 # in months


def append_metering_records(
archive: list,
Expand Down Expand Up @@ -45,3 +55,48 @@ def append_metering_records(
return archive[1:]
else:
return archive


def archive_record(
hook,
config: Config,
billing_record: dict
) -> None:
"""
:param hook:
The Pluggy plugin manager hook that will be
used to call the meter_billing operation.
:param config:
The configuration specifying the metrics that
need to be processed in the usage records list.
:param billing_record:
The dictionary containing the most recent
metering and usage records to be archived.
"""
archive = retry_on_exception(
functools.partial(
hook.get_metering_archive,
config=config,
),
logger=log,
func_name="hook.get_metering_archive"
)

if archive is None:
archive = []

archive = append_metering_records(
archive,
billing_record,
config.archive_retention_period or DEFAULT_RETENTION_PERIOD
)

retry_on_exception(
functools.partial(
hook.save_metering_archive,
config=config,
archive_data=archive
),
logger=log,
func_name="hook.save_metering_archive"
)
15 changes: 15 additions & 0 deletions csp_billing_adapter/bill_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
string_to_date
)
from csp_billing_adapter.config import Config
from csp_billing_adapter.archive import archive_record

log = logging.getLogger('CSPBillingAdapter')

Expand Down Expand Up @@ -655,3 +656,17 @@ def process_metering(
)
csp_config['usage'] = billable_usage
csp_config['last_billed'] = metering_time

# Save last usage and metering records to archive
billing_record = {
'billing_time': metering_time,
'billing_status': billing_status,
'billed_usage': billed_dimensions,
'usage_records': billable_records
}

archive_record(
hook,
config,
billing_record
)
16 changes: 16 additions & 0 deletions csp_billing_adapter/memory_archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,26 @@

import csp_billing_adapter

from csp_billing_adapter.config import Config

memory_archive = []

log = logging.getLogger('CSPBillingAdapter')


@csp_billing_adapter.hookimpl(trylast=True)
def get_archive_location():
"""Retrieve archive location."""
return '/tmp/fake_archive.json'


@csp_billing_adapter.hookimpl(trylast=True)
def get_metering_archive(config: Config):
return memory_archive.copy()


@csp_billing_adapter.hookimpl(trylast=True)
def save_metering_archive(config: Config, archive_data: list):
global memory_archive

memory_archive = archive_data
3 changes: 3 additions & 0 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ def cba_pm(cba_config):
# reset the in-memory csp_config to empty
pm.hook.save_csp_config(config=cba_config, csp_config=dict())

# reset the in-memory archive to empty
pm.hook.save_metering_archive(config=cba_config, archive_data=list())

return pm


Expand Down
45 changes: 44 additions & 1 deletion tests/unit/test_archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
for the archive util functions.
"""

from csp_billing_adapter.archive import append_metering_records
from csp_billing_adapter.archive import (
append_metering_records,
archive_record
)


def test_append_metering_records():
Expand All @@ -40,3 +43,43 @@ def test_append_metering_records():

assert len(archive) == 6
assert archive[4] == records


def test_archive_record(cba_pm, cba_config):
record = {
'billing_time': '2024-02-09T18:11:59.527064+00:00',
'billing_status': {
'tier_1': {
'record_id': 'd92c6e6556b14770994f5b64ebe3d339',
'status': 'succeeded'
}
},
'billed_usage': {
'tier_1': 10
},
'usage_records': [
{
'managed_node_count': 9,
'reporting_time': '2024-01-09T18:11:59.527673+00:00',
'base_product': 'cpe:/o:suse:product:v1.2.3'
},
{
'managed_node_count': 9,
'reporting_time': '2024-01-09T18:11:59.529096+00:00',
'base_product': 'cpe:/o:suse:product:v1.2.3'
},
{
'managed_node_count': 10,
'reporting_time': '2024-01-09T18:11:59.531424+00:00',
'base_product': 'cpe:/o:suse:product:v1.2.3'
}
]
}
archive_record(
cba_pm.hook,
cba_config,
record
)
archive = cba_pm.hook.get_metering_archive(config=cba_config)
assert len(archive) == 1
assert archive[0] == record

0 comments on commit f946719

Please sign in to comment.