Skip to content

Commit

Permalink
Merge branch 'main' into feature/endpoint-ai-insights
Browse files Browse the repository at this point in the history
  • Loading branch information
joeypoon authored Nov 18, 2024
2 parents 6ba79a6 + c473a69 commit eb9ab83
Show file tree
Hide file tree
Showing 34 changed files with 916 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type DateHistogramColumnParams = DateHistogramIndexPatternColumn['params'

export type TopValuesColumnParams = Pick<
TermsIndexPatternColumn['params'],
'size' | 'orderDirection' | 'orderBy' | 'secondaryFields' | 'accuracyMode'
'size' | 'orderDirection' | 'orderBy' | 'secondaryFields' | 'accuracyMode' | 'orderAgg'
>;

export const getHistogramColumn = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const mockKibanaValues = {
indexMappingComponent: null,
isCloud: false,
isSidebarEnabled: true,
kibanaVersion: null,
lens: {
EmbeddableComponent: jest.fn(),
stateHelperApi: jest.fn().mockResolvedValue({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ export interface DockerInstructionsStepProps {
hasApiKey: boolean;
isWaitingForConnector: boolean;
serviceType: string;
connectorVersion: string;
}
export const DockerInstructionsStep: React.FC<DockerInstructionsStepProps> = ({
connectorId,
isWaitingForConnector,
serviceType,
apiKeyData,
connectorVersion,
}) => {
const [isOpen, setIsOpen] = React.useState<EuiAccordionProps['forceState']>('open');
const { elasticsearchUrl } = useCloudDetails();
Expand Down Expand Up @@ -163,7 +165,7 @@ export const DockerInstructionsStep: React.FC<DockerInstructionsStepProps> = ({
showTopBar={false}
languageType="bash"
codeSnippet={getRunFromDockerSnippet({
version: '8.15.0',
version: connectorVersion,
})}
/>
</EuiAccordion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { ConnectorStatus } from '@kbn/search-connectors';

import { Status } from '../../../../../common/types/api';

import { KibanaLogic } from '../../../shared/kibana';
import { GetApiKeyByIdLogic } from '../../api/api_key/get_api_key_by_id_api_logic';

import { GenerateConnectorApiKeyApiLogic } from '../../api/connector/generate_connector_api_key_api_logic';
Expand All @@ -48,6 +49,7 @@ export const ConnectorDeployment: React.FC = () => {
const [selectedDeploymentMethod, setSelectedDeploymentMethod] = useState<'docker' | 'source'>(
'docker'
);
const { kibanaVersion } = useValues(KibanaLogic);
const { generatedData, isGenerateLoading } = useValues(DeploymentLogic);
const { index, isLoading, connector, connectorId } = useValues(ConnectorViewLogic);
const { fetchConnector } = useActions(ConnectorViewLogic);
Expand Down Expand Up @@ -199,6 +201,7 @@ export const ConnectorDeployment: React.FC = () => {
serviceType={connector.service_type ?? ''}
isWaitingForConnector={isWaitingForConnector}
apiKeyData={apiKey}
connectorVersion={kibanaVersion ?? ''}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export const renderApp = (
history,
indexMappingComponent,
isSidebarEnabled,
kibanaVersion,
lens,
ml,
navigateToUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export interface KibanaLogicProps {
history: ScopedHistory;
indexMappingComponent?: React.FC<IndexMappingProps>;
isSidebarEnabled: boolean;
kibanaVersion?: string;
lens?: LensPublicStart;
ml?: MlPluginStart;
navigateToUrl: RequiredFieldsOnly<ApplicationStart['navigateToUrl']>;
Expand Down Expand Up @@ -94,6 +95,7 @@ export interface KibanaValues {
indexMappingComponent: React.FC<IndexMappingProps> | null;
isCloud: boolean;
isSidebarEnabled: boolean;
kibanaVersion: string | null;
lens: LensPublicStart | null;
ml: MlPluginStart | null;
navigateToUrl(path: string, options?: CreateHrefOptions): Promise<void>;
Expand Down Expand Up @@ -133,6 +135,7 @@ export const KibanaLogic = kea<MakeLogicType<KibanaValues>>({
history: [props.history, {}],
indexMappingComponent: [props.indexMappingComponent || null, {}],
isSidebarEnabled: [props.isSidebarEnabled, {}],
kibanaVersion: [props.kibanaVersion || null, {}],
lens: [props.lens || null, {}],
ml: [props.ml || null, {}],
navigateToUrl: [
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/enterprise_search/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ export class EnterpriseSearchPlugin implements Plugin {
this.esConfig = { elasticsearch_host: ELASTICSEARCH_URL_PLACEHOLDER };
}

if (!this.config.host) return; // No API to call
if (this.hasInitialized) return; // We've already made an initial call

try {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/common/experimental_features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const _allowedExperimentalValues = {
useSpaceAwareness: false,
enableReusableIntegrationPolicies: true,
asyncDeployPolicies: true,
enableExportCSV: false,
};

/**
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/fleet/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ export {
INVALID_NAMESPACE_CHARACTERS,
getFileMetadataIndexName,
getFileDataIndexName,
removeSOAttributes,
getSortConfig,
} from './services';

export type { FleetAuthz } from './authz';
Expand Down
29 changes: 29 additions & 0 deletions x-pack/plugins/fleet/common/services/agent_utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { getSortConfig, removeSOAttributes } from './agent_utils';

describe('Agent utils', () => {
it('should get sort config', () => {
const sortConfig = getSortConfig('agent.id', 'asc');
expect(sortConfig).toEqual([{ 'agent.id': { order: 'asc' } }]);
});

it('should get default sort config', () => {
const sortConfig = getSortConfig('enrolled_at', 'desc');
expect(sortConfig).toEqual([
{ enrolled_at: { order: 'desc' } },
{ 'local_metadata.host.hostname.keyword': { order: 'asc' } },
]);
});

it('should remove SO attributes', () => {
const kuery = 'attributes.test AND fleet-agents.test';
const result = removeSOAttributes(kuery);
expect(result).toEqual('test AND test');
});
});
22 changes: 22 additions & 0 deletions x-pack/plugins/fleet/common/services/agent_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export function removeSOAttributes(kuery: string): string {
return kuery.replace(/attributes\./g, '').replace(/fleet-agents\./g, '');
}

export function getSortConfig(
sortField: string,
sortOrder: 'asc' | 'desc'
): Array<Record<string, { order: 'asc' | 'desc' }>> {
const isDefaultSort = sortField === 'enrolled_at' && sortOrder === 'desc';
// if using default sorting (enrolled_at), adding a secondary sort on hostname, so that the results are not changing randomly in case many agents were enrolled at the same time
const secondarySort: Array<Record<string, { order: 'asc' | 'desc' }>> = isDefaultSort
? [{ 'local_metadata.host.hostname.keyword': { order: 'asc' } }]
: [];
return [{ [sortField]: { order: sortOrder } }, ...secondarySort];
}
2 changes: 2 additions & 0 deletions x-pack/plugins/fleet/common/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,5 @@ export {
getFleetServerVersionMessage,
isAgentVersionLessThanFleetServer,
} from './check_fleet_server_versions';

export { removeSOAttributes, getSortConfig } from './agent_utils';
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ const mockedUseLicence = useLicense as jest.MockedFunction<typeof useLicense>;

jest.mock('../../components/agent_reassign_policy_modal');

jest.mock('../hooks/export_csv', () => ({
useExportCSV: jest.fn().mockReturnValue({
generateReportingJobCSV: jest.fn(),
}),
}));

const defaultProps = {
nAgentsInTable: 10,
totalManagedAgentIds: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import { getCommonTags } from '../utils';

import { AgentRequestDiagnosticsModal } from '../../components/agent_request_diagnostics_modal';

import { useExportCSV } from '../hooks/export_csv';

import type { SelectionMode } from './types';
import { TagsAddRemove } from './tags_add_remove';

Expand All @@ -44,6 +46,8 @@ export interface Props {
refreshAgents: (args?: { refreshTags?: boolean }) => void;
allTags: string[];
agentPolicies: AgentPolicy[];
sortField?: string;
sortOrder?: 'asc' | 'desc';
}

export const AgentBulkActions: React.FunctionComponent<Props> = ({
Expand All @@ -56,6 +60,8 @@ export const AgentBulkActions: React.FunctionComponent<Props> = ({
refreshAgents,
allTags,
agentPolicies,
sortField,
sortOrder,
}) => {
const licenseService = useLicense();
const isLicenceAllowingScheduleUpgrade = licenseService.hasAtLeast(LICENSE_FOR_SCHEDULE_UPGRADE);
Expand Down Expand Up @@ -96,7 +102,9 @@ export const AgentBulkActions: React.FunctionComponent<Props> = ({
: nAgentsInTable - totalManagedAgentIds?.length;

const [tagsPopoverButton, setTagsPopoverButton] = useState<HTMLElement>();
const { diagnosticFileUploadEnabled } = ExperimentalFeaturesService.get();
const { diagnosticFileUploadEnabled, enableExportCSV } = ExperimentalFeaturesService.get();

const { generateReportingJobCSV } = useExportCSV(enableExportCSV);

const menuItems = [
{
Expand Down Expand Up @@ -217,6 +225,30 @@ export const AgentBulkActions: React.FunctionComponent<Props> = ({
setIsUnenrollModalOpen(true);
},
},
...(enableExportCSV
? [
{
name: (
<FormattedMessage
id="xpack.fleet.agentBulkActions.exportAgents"
data-test-subj="bulkAgentExportBtn"
defaultMessage="Export {agentCount, plural, one {# agent} other {# agents}} as CSV"
values={{
agentCount,
}}
/>
),
icon: <EuiIcon type="exportAction" size="m" />,
onClick: () => {
closeMenu();
generateReportingJobCSV(agents, {
field: sortField,
direction: sortOrder,
});
},
},
]
: []),
];

const panels = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export interface SearchAndFilterBarProps {
onClickAgentActivity: () => void;
showAgentActivityTour: { isOpen: boolean };
latestAgentActionErrors: number;
sortField?: string;
sortOrder?: 'asc' | 'desc';
}

export const SearchAndFilterBar: React.FunctionComponent<SearchAndFilterBarProps> = ({
Expand Down Expand Up @@ -89,6 +91,8 @@ export const SearchAndFilterBar: React.FunctionComponent<SearchAndFilterBarProps
onClickAgentActivity,
showAgentActivityTour,
latestAgentActionErrors,
sortField,
sortOrder,
}) => {
const authz = useAuthz();

Expand Down Expand Up @@ -219,6 +223,8 @@ export const SearchAndFilterBar: React.FunctionComponent<SearchAndFilterBarProps
refreshAgents={refreshAgents}
allTags={tags}
agentPolicies={agentPolicies}
sortField={sortField}
sortOrder={sortOrder}
/>
</EuiFlexItem>
) : null}
Expand Down
Loading

0 comments on commit eb9ab83

Please sign in to comment.