Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
from collections import defaultdict
from concurrent.futures.thread import ThreadPoolExecutor
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Any, Dict, List, Tuple
from datetime import datetime, date, timedelta

Expand Down Expand Up @@ -205,7 +205,7 @@ def _display_name(storage_type):
})
metrics = aws.get_cloud_watch_metric_data(
region, metric_queries, today,
today - timedelta(days=7))
today - timedelta(days=2))
for md in metrics.get("MetricDataResults", []):
values = md.get("Values") or []
if not values:
Expand All @@ -228,14 +228,21 @@ def _candidates_and_savings(self,
"""
buckets_data = {}
result = []
with ThreadPoolExecutor(max_workers=50) as executor:
if not region_candidates:
return result
cw_clients = {
region: aws.session.client("cloudwatch", region_name=region)
for region in region_candidates
}
max_workers = min(20, sum(len(v) for v in region_candidates.values()))
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = []
for region, candidates in region_candidates.items():
s3_client = aws.session.client("s3", region_name=region)
for cand in candidates:
for region, buckets in region_candidates.items():
cloudwatch = cw_clients[region]
for bucket in buckets:
futures.append(executor.submit(
aws.get_bucket_storage_info, s3_client, cand, ))
for f in futures:
aws.get_bucket_storage_info, cloudwatch, bucket, ))
for f in as_completed(futures):
res = f.result()
if res:
buckets_data.update(res)
Expand Down
1 change: 1 addition & 0 deletions ngui/server/graphql/__generated__/types/restapi.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ngui/server/graphql/typeDefs/restapi/restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ export default gql`
cur_version: Int
config_scheme: String
report_name: String
linked: Boolean
}

input AzureSubscriptionConfigInput {
Expand Down
2 changes: 1 addition & 1 deletion ngui/ui/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type ButtonText = ExclusiveUnion<{
pepega: string;
}>;

type ButtonProps = MuiButtonProps &
export type ButtonProps = MuiButtonProps &
ButtonText &
NavProps & {
dataTestId?: string;
Expand Down
2 changes: 2 additions & 0 deletions ngui/ui/src/components/CanvasBarChart/CanvasBarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ const CanvasBarChart = ({

const ResponsiveCanvasBarChart = ({
data,
wrapperRef,
keys = [],
style = {},
isLoading = false,
Expand All @@ -454,6 +455,7 @@ const ResponsiveCanvasBarChart = ({
style={{
height: muiTheme.spacing(height)
}}
ref={wrapperRef}
>
<ResponsiveWrapper>
{({ width: wrapperWidth, height: wrapperHeight }) => {
Expand Down
8 changes: 7 additions & 1 deletion ngui/ui/src/components/CloudResourceId/CloudResourceId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ const CloudResourceId = (props) => {

// Additional check to handle cloudResourceIdentifier having 'null' or 'undefined' substring
if (separator && cloudResourceIdentifier.includes(separator)) {
const shortenedCloudResourceId = `${SHORTENED_CLOUD_RESOURCE_ID_PREFIX}${cloudResourceIdentifier.split(separator).pop()}`;
// If the path ends with "/", take last 3 segments (last segment is empty)
// Example: "path/to/resource/" -> ["to", "resource", ""] -> "to/resource/"
const shortId = cloudResourceIdentifier.endsWith(separator)
? cloudResourceIdentifier.split(separator).slice(-3).join(separator)
: cloudResourceIdentifier.split(separator).pop();

const shortenedCloudResourceId = `${SHORTENED_CLOUD_RESOURCE_ID_PREFIX}${shortId}`;

return (
<CloudResourceIdString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,25 @@ import AwsUseAwsEdpDiscount from "../AwsUseAwsEdpDiscount";

const AwsAssumedRoleInputs = ({
readOnlyFields = [],
showAssumedRoleCredentialsInModal = false
showAssumedRoleCredentialsInModal = false,
showAdvancedOptions = true
}: {
readOnlyFields?: string[];
showAssumedRoleCredentialsInModal?: boolean;
showAdvancedOptions?: boolean;
}) => (
<>
<AwsAssumedRoleCredentials readOnlyFields={readOnlyFields} />
<AwsUseAwsEdpDiscount />
<Typography gutterBottom data-test-id="p_cost_and_usage_report_parameters_description">
<FormattedMessage id="costAndUsageReportParametersDescription" />
</Typography>
<AwsExportType />
<AwsBillingBucketInputs showAssumedRoleCredentialsInModal={showAssumedRoleCredentialsInModal} />
{showAdvancedOptions && (
<>
<AwsUseAwsEdpDiscount />
<Typography gutterBottom data-test-id="p_cost_and_usage_report_parameters_description">
<FormattedMessage id="costAndUsageReportParametersDescription" />
</Typography>
<AwsExportType />
<AwsBillingBucketInputs showAssumedRoleCredentialsInModal={showAssumedRoleCredentialsInModal} />
</>
)}
</>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ const AwsProperties = ({ accountId, config, createdAt }: AwsPropertiesProps) =>

const getAwsAccountTypeMessageId = () => {
if (linked) {
return "linked";
return "member";
}

return "managementStandalone";
};

const getAwsAuthenticationTypeMessageId = () => {
if (isAssumeRole) {
return "assumedRole";
}

return "root";
return "accessKey";
};

return (
Expand Down Expand Up @@ -57,6 +61,11 @@ const AwsProperties = ({ accountId, config, createdAt }: AwsPropertiesProps) =>
value: `p_${AWS_CNR}_value`
}}
/>
<KeyValueLabel
keyMessageId="awsAuthenticationType"
value={<FormattedMessage id={getAwsAuthenticationTypeMessageId()} />}
dataTestIds={{ key: "p_authentication_type_key", value: "p_authentication_type_value" }}
/>
{isAssumeRole && (
<KeyValueLabel
keyMessageId="awsRoleName"
Expand Down
25 changes: 12 additions & 13 deletions ngui/ui/src/components/WrapperCard/WrapperCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,30 @@ import IconButton from "components/IconButton";
import Tooltip from "components/Tooltip";
import WidgetTitle from "components/WidgetTitle";
import WrapperCardTitlePdf from "components/WrapperCardTitlePdf/WrapperCardTitlePdf";
import { TitleProps, WrapperCardProps } from "./types";
import useStyles from "./WrapperCard.styles";

const renderButton = (type, buttonProps) => (type === "icon" ? <IconButton {...buttonProps} /> : <Button {...buttonProps} />);
const Title = ({ title, titleButton, dataTestId }: TitleProps) => {
const titleMessage = <WidgetTitle dataTestId={dataTestId}>{title}</WidgetTitle>;

const renderTitleButton = (options) => {
const { type, tooltip, buttonProps } = options;
return tooltip ? <Tooltip title={tooltip.title}>{renderButton(type, buttonProps)}</Tooltip> : renderButton(type, buttonProps);
};
if (!titleButton) {
return titleMessage;
}

const Title = ({ title, titleButton, dataTestId }) => {
const titleMessage = <WidgetTitle dataTestId={dataTestId}>{title}</WidgetTitle>;
const { type, tooltip, buttonProps } = titleButton;
const buttonElement = type === "icon" ? <IconButton {...buttonProps} /> : <Button {...buttonProps} />;

const button = titleButton && renderTitleButton(titleButton);
const button = tooltip ? <Tooltip title={tooltip.title}>{buttonElement}</Tooltip> : buttonElement;

return button ? (
return (
<Box display="flex" alignItems="center">
{titleButton.type === "icon" ? titleMessage : <Box mr={1}>{titleMessage}</Box>}
{type === "icon" ? titleMessage : <Box mr={1}>{titleMessage}</Box>}
{button}
</Box>
) : (
titleMessage
);
};

const WrapperCard = forwardRef(
const WrapperCard = forwardRef<HTMLDivElement, WrapperCardProps>(
(
{
title,
Expand Down
54 changes: 54 additions & 0 deletions ngui/ui/src/components/WrapperCard/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { ReactNode } from "react";
import type { CardProps } from "@mui/material";
import { ButtonProps } from "components/Button/Button";
import { IconButtonProps } from "components/IconButton/IconButton";
import { TODO } from "utils/types";

type ButtonConfig =
| {
type: "icon";
buttonProps: IconButtonProps;
}
| {
type: "button";
buttonProps: ButtonProps;
};

type TitleButtonOptions = {
tooltip?: { title: ReactNode };
} & ButtonConfig;

type DataTestIdsOptions = {
wrapper?: string;
title?: string;
titleCaption?: string;
button?: string;
};

type ButtonOptions = {
show: boolean;
href?: string;
link?: string;
messageId: string;
};

export type TitleProps = {
title: ReactNode;
titleButton?: TitleButtonOptions;
dataTestId?: string;
};

export type WrapperCardProps = Omit<CardProps, "title"> & {
title: ReactNode;
titleCaption?: ReactNode;
titleButton?: TitleButtonOptions;
dataTestIds?: DataTestIdsOptions;
children?: ReactNode;
className?: string;
button?: ButtonOptions;
needAlign?: boolean;
titlePdf?: {
id: string;
renderData: () => TODO;
};
};
Loading