Skip to content

Commit

Permalink
Pull request update/241219
Browse files Browse the repository at this point in the history
d9dc929 OS-3669. Update booking labels
cddcc0a OS-4151. Re-request resources after applying force assignment rules
ad8ab1e OS-4548. Fixed missing organization_id field in saving_spike task
0222966 OS-5101. Fixed showing deleted env resources in pool api
  • Loading branch information
stanfra authored Dec 19, 2024
2 parents f0fb8b9 + d9dc929 commit ac14897
Show file tree
Hide file tree
Showing 17 changed files with 205 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def _get(self):
modules_data.sort(key=lambda x: x['saving'], reverse=True)
task = {
"object_id": self.organization_id,
"organization_id": self.organization_id,
"object_type": "organization",
"action": "saving_spike",
"meta": {"previous_total": previous_total,
Expand Down
1 change: 1 addition & 0 deletions ngui/ui/src/api/restapi/actionCreators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,7 @@ export const applyAssignmentRules = (organizationId, params) =>
url: `${API_URL}/organizations/${organizationId}/rules_apply`,
method: "POST",
label: APPLY_ASSIGNMENT_RULES,
affectedRequests: [GET_CLEAN_EXPENSES],
params: {
pool_id: params.poolId,
include_children: params.includeChildren
Expand Down
35 changes: 35 additions & 0 deletions ngui/ui/src/components/CurrentBooking/AvailableIn/AvailableIn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import KeyValueLabel from "components/KeyValueLabel/KeyValueLabel";
import { useFormatIntervalDuration } from "hooks/useFormatIntervalDuration";
import { INTERVAL_DURATION_VALUE_TYPES } from "utils/datetime";

type AvailableInProps = {
remained: {
weeks: number;
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
};
};

const AvailableIn = ({ remained }: AvailableInProps) => {
const formatInterval = useFormatIntervalDuration();

return (
<KeyValueLabel
keyMessageId="availableIn"
value={formatInterval({
formatTo: [
INTERVAL_DURATION_VALUE_TYPES.WEEKS,
INTERVAL_DURATION_VALUE_TYPES.DAYS,
INTERVAL_DURATION_VALUE_TYPES.HOURS,
INTERVAL_DURATION_VALUE_TYPES.MINUTES
],
duration: remained
})}
/>
);
};

export default AvailableIn;
3 changes: 3 additions & 0 deletions ngui/ui/src/components/CurrentBooking/AvailableIn/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import AvailableIn from "./AvailableIn";

export default AvailableIn;
11 changes: 6 additions & 5 deletions ngui/ui/src/components/CurrentBooking/CurrentBooking.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { FormattedMessage } from "react-intl";
import JiraIssuesAttachments from "components/JiraIssuesAttachments";
import KeyValueLabel from "components/KeyValueLabel/KeyValueLabel";
import { BookingTimeMeasure, getBookingTimeMeasuresDefinition } from "components/UpcomingBooking";
import { INFINITY_SIGN } from "utils/constants";
import { getBookingTimeMeasuresDefinition } from "components/UpcomingBooking";
import AvailableIn from "./AvailableIn";

// TODO: generalize Current and Upcoming bookings
const CurrentBooking = ({ employeeName, acquiredSince, releasedAt, jiraIssues = [] }) => {
const { remained } = getBookingTimeMeasuresDefinition({ releasedAt, acquiredSince });
const { remained, bookedUntil } = getBookingTimeMeasuresDefinition({ releasedAt, acquiredSince });

return (
<>
<KeyValueLabel keyMessageId="user" value={employeeName} />
{remained !== INFINITY_SIGN && <BookingTimeMeasure messageId="availableIn" measure={remained} />}
<KeyValueLabel keyMessageId="until" value={bookedUntil === Infinity ? <FormattedMessage id="infinite" /> : bookedUntil} />
{remained !== Infinity && <AvailableIn remained={remained} />}
{jiraIssues.length > 0 && <JiraIssuesAttachments issues={jiraIssues} />}
</>
);
Expand Down

This file was deleted.

This file was deleted.

35 changes: 35 additions & 0 deletions ngui/ui/src/components/UpcomingBooking/Duration/Duration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import KeyValueLabel from "components/KeyValueLabel/KeyValueLabel";
import { useFormatIntervalDuration } from "hooks/useFormatIntervalDuration";
import { INTERVAL_DURATION_VALUE_TYPES } from "utils/datetime";

type DurationProps = {
duration: {
weeks: number;
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
};
};

const Duration = ({ duration }: DurationProps) => {
const formatInterval = useFormatIntervalDuration();

return (
<KeyValueLabel
keyMessageId="duration"
value={formatInterval({
formatTo: [
INTERVAL_DURATION_VALUE_TYPES.WEEKS,
INTERVAL_DURATION_VALUE_TYPES.DAYS,
INTERVAL_DURATION_VALUE_TYPES.HOURS,
INTERVAL_DURATION_VALUE_TYPES.MINUTES
],
duration
})}
/>
);
};

export default Duration;
3 changes: 3 additions & 0 deletions ngui/ui/src/components/UpcomingBooking/Duration/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Duration from "./Duration";

export default Duration;
41 changes: 27 additions & 14 deletions ngui/ui/src/components/UpcomingBooking/UpcomingBooking.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import { FormattedMessage } from "react-intl";
import KeyValueLabel from "components/KeyValueLabel/KeyValueLabel";
import { INFINITY_SIGN } from "utils/constants";
import { EN_FULL_FORMAT, format, secondsToMilliseconds, intervalToDuration } from "utils/datetime";
import BookingTimeMeasure from "./BookingTimeMeasure";
import Duration from "./Duration";

const getInfiniteBookingTimeMeasuresDefinition = (acquiredSince) => ({
duration: INFINITY_SIGN,
remained: INFINITY_SIGN,
bookedUntil: INFINITY_SIGN,
// TODO: generalize getBookedSince in InfiniteBookingTimeMeasures and FiniteBookingTimeMeasures
bookedSince: format(secondsToMilliseconds(acquiredSince), EN_FULL_FORMAT)
});
type UpcomingBookingProps = {
employeeName: string;
acquiredSince: number;
releasedAt: number;
};

const getInfiniteBookingTimeMeasuresDefinition = (acquiredSince: number) =>
({
duration: Infinity,
remained: Infinity,
bookedUntil: Infinity,
// TODO: generalize getBookedSince in InfiniteBookingTimeMeasures and FiniteBookingTimeMeasures
bookedSince: format(secondsToMilliseconds(acquiredSince), EN_FULL_FORMAT)
}) as const;

const getFiniteBookingTimeMeasuresDefinition = (acquiredSince, releasedAt) => {
const getFiniteBookingTimeMeasuresDefinition = (acquiredSince: number, releasedAt: number) => {
const acquiredSinceInMilliseconds = secondsToMilliseconds(acquiredSince);
const releasedAtInMilliseconds = secondsToMilliseconds(releasedAt);

Expand All @@ -29,23 +36,29 @@ const getFiniteBookingTimeMeasuresDefinition = (acquiredSince, releasedAt) => {
};
};

export const getBookingTimeMeasuresDefinition = ({ releasedAt, acquiredSince }) => {
export const getBookingTimeMeasuresDefinition = ({
releasedAt,
acquiredSince
}: {
releasedAt: number;
acquiredSince: number;
}) => {
const timeMeasuresDefinition =
releasedAt === 0
? getInfiniteBookingTimeMeasuresDefinition(acquiredSince)
: getFiniteBookingTimeMeasuresDefinition(acquiredSince, releasedAt);
return timeMeasuresDefinition;
};

const UpcomingBooking = ({ employeeName, acquiredSince, releasedAt }) => {
const UpcomingBooking = ({ employeeName, acquiredSince, releasedAt }: UpcomingBookingProps) => {
const { bookedSince, bookedUntil, duration } = getBookingTimeMeasuresDefinition({ releasedAt, acquiredSince });

return (
<>
<KeyValueLabel keyMessageId="user" value={employeeName} />
<KeyValueLabel keyMessageId="since" value={bookedSince} />
<KeyValueLabel keyMessageId="until" value={bookedUntil} />
<BookingTimeMeasure messageId="duration" measure={duration} />
<KeyValueLabel keyMessageId="until" value={bookedUntil === Infinity ? <FormattedMessage id="infinite" /> : bookedUntil} />
{bookedUntil !== Infinity && <Duration duration={duration} />}
</>
);
};
Expand Down
3 changes: 1 addition & 2 deletions ngui/ui/src/components/UpcomingBooking/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import BookingTimeMeasure from "./BookingTimeMeasure";
import UpcomingBooking, { getBookingTimeMeasuresDefinition } from "./UpcomingBooking";

export { BookingTimeMeasure, getBookingTimeMeasuresDefinition };
export { getBookingTimeMeasuresDefinition };
export default UpcomingBooking;
1 change: 1 addition & 0 deletions ngui/ui/src/translations/en-US/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@
"incorrectDateFormat": "Incorrect date format",
"independentCompute": "Independent compute",
"independentComputeTooltip": "Region is recommended for running new workloads that are mostly independent from the existing ones",
"infinite": "Infinite",
"infinity": "Infinity",
"info": "Info",
"infrastructure": "Infrastructure",
Expand Down
2 changes: 0 additions & 2 deletions ngui/ui/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,6 @@ export const ALERT_SEVERITY = Object.freeze({
WARNING: "warning"
});

export const INFINITY_SIGN = "∞";

export const ENVIRONMENT_SOFTWARE_FIELD = "Software ";
export const ENVIRONMENT_JIRA_TICKETS_FIELD = "Jira tickets ";
export const ENVIRONMENT_TOUR_IDS_BY_DYNAMIC_FIELDS = Object.freeze({
Expand Down
4 changes: 3 additions & 1 deletion rest_api/rest_api_server/controllers/expense.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def _get_expenses_clickhouse(
'_last_seen_date': {'$gte': start_date.replace(
hour=0, minute=0, second=0, microsecond=0)},
'last_seen': {'$gte': int(start_date.timestamp())},
'deleted_at': 0
}, resource_fields)

external_resource_table = [{
Expand All @@ -75,7 +76,8 @@ def _get_expenses_clickhouse(
expenses_results = self.execute_clickhouse(
query="""
SELECT
date, group_field, cloud_account_id, SUM(cost * sign) AS total_cost
date, group_field, cloud_account_id,
SUM(cost * sign) AS total_cost
FROM expenses
JOIN resources ON expenses.resource_id = resources._id
AND expenses.cloud_account_id = resources.cloud_account_id
Expand Down
37 changes: 25 additions & 12 deletions rest_api/rest_api_server/tests/unittests/test_budget_expenses.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,30 +72,42 @@ def setUp(self, version='v2'):
day_in_current2 = datetime(2020, 1, 18)

# org pool
self.add_expense(day_in_last, 3, self.cloud_acc1['id'], self.org['pool_id'])
self.add_expense(day_in_current, 1, self.cloud_acc1['id'], self.org['pool_id'])
self.add_expense(day_in_last, 3, self.cloud_acc1['id'],
self.org['pool_id'])
self.add_expense(day_in_current, 1, self.cloud_acc1['id'],
self.org['pool_id'])

# child1
self.add_expense(day_in_last, 7, self.cloud_acc1['id'], self.child1['id'])
self.add_expense(day_in_current, 10, self.cloud_acc1['id'], self.child1['id'])
self.add_expense(day_in_last, 7, self.cloud_acc1['id'],
self.child1['id'])
self.add_expense(day_in_current, 10, self.cloud_acc1['id'],
self.child1['id'])

# child1_1
self.add_expense(day_in_current, 3, self.cloud_acc1['id'], self.child1_1['id'])
self.add_expense(day_in_current, 3, self.cloud_acc1['id'],
self.child1_1['id'])

# child1_2
self.add_expense(day_in_last, 4, self.cloud_acc1['id'], self.child1_2['id'])
self.add_expense(day_in_last, 4, self.cloud_acc1['id'],
self.child1_2['id'])

# child2_1 in cloud 2
self.add_expense(day_in_current, 5, self.cloud_acc2['id'], self.child2_1['id'])
self.add_expense(day_in_current, 5, self.cloud_acc2['id'],
self.child2_1['id'])

# org2
self.add_expense(day_in_last, 3000, self.cloud_acc_org2['id'], self.org2['pool_id'])
self.add_expense(day_in_last2, 4000, self.cloud_acc_org2['id'], self.org2['pool_id'])
self.add_expense(day_in_current, 4999, self.cloud_acc_org2['id'], self.org2['pool_id'])
self.add_expense(day_in_current2, 4111, self.cloud_acc_org2['id'], self.org2['pool_id'])
self.add_expense(day_in_last, 3000, self.cloud_acc_org2['id'],
self.org2['pool_id'])
self.add_expense(day_in_last2, 4000, self.cloud_acc_org2['id'],
self.org2['pool_id'])
self.add_expense(day_in_current, 4999, self.cloud_acc_org2['id'],
self.org2['pool_id'])
self.add_expense(day_in_current2, 4111, self.cloud_acc_org2['id'],
self.org2['pool_id'])

self.today_ts = int(datetime(2020, 1, 20, 17, 34, 00).timestamp())
self.last_month_ts = int(datetime(2019, 12, 31, 23, 59, 59).timestamp())
self.last_month_ts = int(datetime(
2019, 12, 31, 23, 59, 59).timestamp())
self.this_month_ts = int(datetime(2020, 1, 31, 23, 59, 59).timestamp())
self.p_assign = patch(
'rest_api.rest_api_server.controllers.pool.PoolController.'
Expand All @@ -116,6 +128,7 @@ def add_expense(self, day, cost, cloud, pool, resource_id=None):
'_first_seen_date': timestamp_to_day_start(timestamp),
'last_seen': timestamp,
'_last_seen_date': timestamp_to_day_start(timestamp),
'deleted_at': 0
}
self.resources_collection.insert_one(resource)
resource_id = resource['_id']
Expand Down
16 changes: 10 additions & 6 deletions rest_api/rest_api_server/tests/unittests/test_mytasks_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,12 @@ def setUp(self, version='v2'):
self.assertEqual(code, 201)

self._mock_auth_user(self.user_id)
patch('rest_api.rest_api_server.handlers.v2.my_tasks.MyTasksAsyncHandler.'
'check_cluster_secret', return_value=False).start()
patch('rest_api.rest_api_server.controllers.assignment.AssignmentController.'
'_authorize_action_for_pool', return_value=True).start()
patch('rest_api.rest_api_server.handlers.v2.my_tasks.'
'MyTasksAsyncHandler.check_cluster_secret',
return_value=False).start()
patch('rest_api.rest_api_server.controllers.assignment.'
'AssignmentController._authorize_action_for_pool',
return_value=True).start()

def test_get_my_tasks_no_types(self):
code, tasks = self.client.my_tasks_get(self.org_id)
Expand Down Expand Up @@ -157,7 +159,8 @@ def add_outgoing_assignment_request(self, resource_id=None):
self.assertEqual(code, 201)
return request

def add_expense_records(self, pool_id=None, cost=1, date=None, owner_id=None):
def add_expense_records(self, pool_id=None, cost=1, date=None,
owner_id=None):
if not date:
date = utcnow()
date = date.replace(hour=0, minute=0, second=0, microsecond=0)
Expand All @@ -176,7 +179,8 @@ def add_expense_records(self, pool_id=None, cost=1, date=None, owner_id=None):
'first_seen': int(date.timestamp()),
'_first_seen_date': date,
'last_seen': int(date.timestamp()),
'_last_seen_date': date
'_last_seen_date': date,
'deleted_at': 0
}
self.resources_collection.insert_one(resource)
self.expenses.append({
Expand Down
Loading

0 comments on commit ac14897

Please sign in to comment.