diff --git a/arcee/arcee_receiver/requirements.txt b/arcee/arcee_receiver/requirements.txt index bd5a00998..090ba3f86 100644 --- a/arcee/arcee_receiver/requirements.txt +++ b/arcee/arcee_receiver/requirements.txt @@ -1,7 +1,8 @@ aiohttp==3.10.2 sanic==23.12.1 sanic-ext==23.12.0 -motor==3.4.0 +motor==3.6.0 +pymongo==4.9.1 python-etcd==0.4.5 mongodb-migrations==1.2.1 pydantic==2.4.2 diff --git a/bulldozer/bulldozer_api/requirements.txt b/bulldozer/bulldozer_api/requirements.txt index 5aed6609f..1feeacc9e 100644 --- a/bulldozer/bulldozer_api/requirements.txt +++ b/bulldozer/bulldozer_api/requirements.txt @@ -1,6 +1,7 @@ aiohttp==3.10.2 sanic==23.12.1 -motor==3.4.0 +motor==3.6.0 +pymongo==4.9.1 websockets==12.0 kombu==5.3.4 mongodb-migrations==1.2.1 diff --git a/diworker/diworker/importers/aws.py b/diworker/diworker/importers/aws.py index 08fbf33db..6f6ec42e9 100644 --- a/diworker/diworker/importers/aws.py +++ b/diworker/diworker/importers/aws.py @@ -47,6 +47,7 @@ AWS_CUR_PREFIX_MAP = { 'identity': (False, []), 'bill': (False, []), + 'discount': (False, []), 'line_item': (False, []), 'product': (True, ['product_name', 'purchase_option', 'size_flex']), 'pricing': (True, ['rate_code', 'rate_id', 'purchase_option', diff --git a/diworker/diworker/migrations/202409171620000_fix_discount_fields_names.py b/diworker/diworker/migrations/202409171620000_fix_discount_fields_names.py new file mode 100644 index 000000000..a4054516b --- /dev/null +++ b/diworker/diworker/migrations/202409171620000_fix_discount_fields_names.py @@ -0,0 +1,48 @@ +import logging +from optscale_client.rest_api_client.client_v2 import Client as RestClient +from diworker.diworker.migrations.base import BaseMigration +""" +Fixed names for discount fields in AWS expenses +""" +LOG = logging.getLogger(__name__) + + +class Migration(BaseMigration): + @property + def rest_cl(self): + if self._rest_cl is None: + self._rest_cl = RestClient( + url=self.config_cl.restapi_url(), + secret=self.config_cl.cluster_secret()) + return self._rest_cl + + @property + def mongo_raw(self): + return self.db.raw_expenses + + def get_cloud_accs(self): + cloud_accounts_ids = set() + _, organizations = self.rest_cl.organization_list({ + 'with_connected_accounts': True, 'is_demo': False}) + for org in organizations['organizations']: + _, accounts = self.rest_cl.cloud_account_list( + org['id'], type='aws_cnr') + for cloud_account in accounts['cloud_accounts']: + if cloud_account['auto_import']: + cloud_accounts_ids.add(cloud_account['id']) + return cloud_accounts_ids + + def upgrade(self): + cloud_accs = self.get_cloud_accs() + for i, cloud_acc_id in enumerate(cloud_accs): + LOG.info('Starting processing for cloud account %s (%s/%s)' % ( + cloud_acc_id, i+1, len(cloud_accs))) + self.db.raw_expenses.update_many( + {'bill/BillingPeriodStartDate': {'$exists': True}, + 'cloud_account_id': cloud_acc_id}, + {'$rename': { + 'discount_total_discount': 'discount/TotalDiscount', + 'discount_bundled_discount': 'discount/BundledDiscount'}}) + + def downgrade(self): + pass diff --git a/ngui/ui/src/components/TagKey/TagKey.test.tsx b/ngui/ui/src/components/TagKey/TagKey.test.tsx deleted file mode 100644 index 63f644b6c..000000000 --- a/ngui/ui/src/components/TagKey/TagKey.test.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { createRoot } from "react-dom/client"; -import TestProvider from "tests/TestProvider"; -import TagKey from "./TagKey"; - -it("renders without crashing", () => { - const div = document.createElement("div"); - const root = createRoot(div); - root.render( - - - - ); - root.unmount(); -}); diff --git a/ngui/ui/src/components/TagKey/TagKey.tsx b/ngui/ui/src/components/TagKey/TagKey.tsx deleted file mode 100644 index d17057a01..000000000 --- a/ngui/ui/src/components/TagKey/TagKey.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { FormattedMessage } from "react-intl"; - -const TagKey = ({ tagKey }) => (tagKey === null ? : tagKey); - -export default TagKey; diff --git a/ngui/ui/src/components/TagKey/index.ts b/ngui/ui/src/components/TagKey/index.ts deleted file mode 100644 index d625648ce..000000000 --- a/ngui/ui/src/components/TagKey/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import TagKey from "./TagKey"; - -export default TagKey; diff --git a/ngui/ui/src/components/TagsBreakdown/TagsBreakdownTable/TagsBreakdownTable.tsx b/ngui/ui/src/components/TagsBreakdown/TagsBreakdownTable/TagsBreakdownTable.tsx index 75d967b12..70b3c0884 100644 --- a/ngui/ui/src/components/TagsBreakdown/TagsBreakdownTable/TagsBreakdownTable.tsx +++ b/ngui/ui/src/components/TagsBreakdown/TagsBreakdownTable/TagsBreakdownTable.tsx @@ -1,24 +1,18 @@ import { useMemo } from "react"; import BarChartOutlinedIcon from "@mui/icons-material/BarChartOutlined"; -import { FormattedMessage } from "react-intl"; +import { FormattedMessage, useIntl } from "react-intl"; import FormattedMoney from "components/FormattedMoney"; import Table from "components/Table"; import TableCellActions from "components/TableCellActions"; import TableLoader from "components/TableLoader"; -import TagKey from "components/TagKey"; import TextWithDataTestId from "components/TextWithDataTestId"; import TextWithDate from "components/TextWithDate"; import { FORMATTED_MONEY_TYPES } from "utils/constants"; -const getTotalBreakdownTableData = (counts) => - Object.entries(counts).map(([id, { name = "", ...details }]) => ({ - id: id ?? name, - name, - ...details - })); - const TagsBreakdownTable = ({ data, appliedRange, isLoading, selectedTag, onShowOnChartClick }) => { - const tableData = useMemo(() => getTotalBreakdownTableData(data), [data]); + const tableData = useMemo(() => data, [data]); + + const intl = useIntl(); const columns = useMemo( () => [ @@ -28,8 +22,12 @@ const TagsBreakdownTable = ({ data, appliedRange, isLoading, selectedTag, onShow ), - accessorKey: "tag", - cell: ({ cell }) => + id: "tagKey", + accessorFn: ({ tag }) => + tag ?? + intl.formatMessage({ + id: "(untagged)" + }) }, { header: ( @@ -81,7 +79,7 @@ const TagsBreakdownTable = ({ data, appliedRange, isLoading, selectedTag, onShow ) } ], - [appliedRange.startSecondsTimestamp, appliedRange.endSecondsTimestamp, onShowOnChartClick, selectedTag] + [appliedRange.startSecondsTimestamp, appliedRange.endSecondsTimestamp, intl, selectedTag, onShowOnChartClick] ); return isLoading ? ( diff --git a/rest_api/live_demo.tar.xz b/rest_api/live_demo.tar.xz index 5480e7bfc..8e681ca41 100644 Binary files a/rest_api/live_demo.tar.xz and b/rest_api/live_demo.tar.xz differ diff --git a/rest_api/rest_api_server/controllers/live_demo.py b/rest_api/rest_api_server/controllers/live_demo.py index 98a2882ea..182de8cc1 100644 --- a/rest_api/rest_api_server/controllers/live_demo.py +++ b/rest_api/rest_api_server/controllers/live_demo.py @@ -50,8 +50,8 @@ TOP_NO_DUPLICATE_RESOURCES = 10 DUPLICATION_FORMAT = '-x{ending}' WITH_SUBPOOLS_SIGN = '+' -MIN_RUN_DURATION = 7 * 60 * 60 -MAX_RUN_DURATION = 24 * 60 * 60 +MIN_RUN_DURATION = 14 * 60 * 60 +MAX_RUN_DURATION = 48 * 60 * 60 RECOMMENDATION_MULTIPLIED_FIELDS = ['saving', 'annually_monthly_saving', 'monthly_saving'] PREPARED_DEMO_LIFETIME_DAYS = 3