fleet/frontend/interfaces/schedulable_query.ts
Scott Gress 096a747739
Ability to add labels to queries (front end) (#26867)
For #26649 

# Checklist for submitter

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files)
for more information.

## Details

This PR adds the ability to select labels when saving or editing a query
in the UI, so that the query will only target hosts with those labels.
It follows the API design from
https://github.com/fleetdm/fleet/pull/26589, utilizing the
`labels_include_any` field. The expectation is that when creating or
updating a query, `labels_include_any` is an array of label names, and
when fetching a single query, `labels_include_any` is an array of
objects with a `name` and an `id` key.

As part of this work the `TargetLabelSelector` component is updated to
allow it to show a message in place of the dropdown when there are no
custom options (e.g. "include any", "include all", "exclude any") to
choose from.
2025-03-12 11:54:29 -07:00

158 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// for legacy legacy query stats interface
import PropTypes from "prop-types";
import { IFormField } from "./form_field";
import { IPack } from "./pack";
import {
CommaSeparatedPlatformString,
QueryablePlatform,
SelectedPlatform,
} from "./platform";
import { ILabelQuery } from "./label";
// Query itself
export interface ISchedulableQuery {
created_at: string;
updated_at: string;
id: number;
name: string;
description: string;
query: string;
team_id: number | null;
interval: number;
platform: CommaSeparatedPlatformString; // Might more accurately be called `platforms_to_query` or `targeted_platforms` comma-separated string of platforms to query, default all platforms if omitted
min_osquery_version: string;
automations_enabled: boolean;
logging: QueryLoggingOption;
saved: boolean;
author_id: number;
author_name: string;
author_email: string;
observer_can_run: boolean;
discard_data: boolean;
packs: IPack[];
stats: ISchedulableQueryStats;
editingExistingQuery?: boolean;
labels_include_any?: ILabelQuery[];
}
export interface IEnhancedQuery extends ISchedulableQuery {
performance: string;
targetedPlatforms: QueryablePlatform[];
}
export interface ISchedulableQueryStats {
user_time_p50?: number | null;
user_time_p95?: number | null;
system_time_p50?: number | null;
system_time_p95?: number | null;
total_executions?: number;
}
// legacy
export default PropTypes.shape({
user_time_p50: PropTypes.number,
user_time_p95: PropTypes.number,
system_time_p50: PropTypes.number,
system_time_p95: PropTypes.number,
total_executions: PropTypes.number,
});
// API shapes
// Get a query by id
/** GET /api/v1/fleet/queries/{id}` */
export interface IGetQueryResponse {
query: ISchedulableQuery;
}
// List global or team queries
/** GET /api/v1/fleet/queries?order_key={column_from_queries_table}&order_direction={asc|desc}&team_id={team_id} */
export interface IListQueriesResponse {
queries: ISchedulableQuery[];
}
export interface IQueryKeyQueriesLoadAll {
scope: "queries";
teamId?: number;
page?: number;
perPage?: number;
query?: string;
orderDirection?: "asc" | "desc";
orderKey?: string;
mergeInherited?: boolean;
targetedPlatform?: SelectedPlatform;
}
// Create a new query
/** POST /api/v1/fleet/queries */
export interface ICreateQueryRequestBody {
name: string;
query: string;
description?: string;
observer_can_run?: boolean;
discard_data?: boolean;
team_id?: number; // global query if ommitted
interval?: number; // default 0 means never run
platform?: CommaSeparatedPlatformString; // Might more accurately be called `platforms_to_query` comma-separated string of platforms to query, default all platforms if omitted
min_osquery_version?: string; // default all versions if ommitted
automations_enabled?: boolean; // whether to send data to the configured log destination according to the query's `interval`. Default false if ommitted.
logging?: QueryLoggingOption;
labels_include_any?: string[];
}
// response is ISchedulableQuery
// Modify a query by id
/** PATCH /api/v1/fleet/queries/{id} */
export interface IModifyQueryRequestBody
extends Omit<ICreateQueryRequestBody, "name" | "query"> {
id?: number;
name?: string;
query?: string;
description?: string;
observer_can_run?: boolean;
discard_data?: boolean;
frequency?: number;
platform?: CommaSeparatedPlatformString;
min_osquery_version?: string;
automations_enabled?: boolean;
}
// response is ISchedulableQuery // better way to indicate this?
// Delete a query by name
/** DELETE /api/v1/fleet/queries/{name} */
export interface IDeleteQueryRequestBody {
team_id?: number; // searches for a global query if omitted
}
// Delete a query by id
// DELETE /api/v1/fleet/queries/id/{id}
// (no body)
// Delete queries by id
/** POST /api/v1/fleet/queries/delete */
export interface IDeleteQueriesRequestBody {
ids: number[];
}
export interface IDeleteQueriesResponse {
deleted: number; // number of queries deleted
}
export interface IEditQueryFormFields {
name: IFormField<string>;
description: IFormField<string>;
query: IFormField<string>;
observer_can_run: IFormField<boolean>;
discard_data: IFormField<boolean>;
frequency: IFormField<number>;
automations_enabled: IFormField<boolean>;
platforms: IFormField<CommaSeparatedPlatformString>;
min_osquery_version: IFormField<string>;
logging: IFormField<QueryLoggingOption>;
}
export type QueryLoggingOption =
| "snapshot"
| "differential"
| "differential_ignore_removals";