mirror of
https://github.com/elastic/kibana.git
synced 2025-04-18 23:21:39 -04:00
[Oblt Onboarding] Remove Custom Logs flow (#216053)
Closes https://github.com/elastic/kibana/issues/208025 This change deleted the "Stream log files" onboarding flow which is now replaced by the Auto Detect flow. | Before | After | | --- | --- | |  |  | Changes made: * Deleted UI components responsible for rendering the Custom Logs flow * Deleted the definition for a custom card in the onboarding search results * Deleted API endpoints and supporting files used only by the Custom Logs flow * `/internal/observability_onboarding/logs/setup/environment` endpoint was still used by the OTel Host flow, so it was moved to a dedicated OTel route and pathname changed to `/internal/observability_onboarding/otel_host/setup` * Functionality of the `/internal/observability_onboarding/otel/api_key` endpoint was merged into the above mentioned OTel route, so UI has to make a single API request to get all the necessary information from the server * Deleted Scout UI tests for the Custom Logs flow * Deleted API integration tests for the deleted endpoints * API tests that we previously testing `/internal/observability_onboarding/logs/flow` were converted to test `/internal/observability_onboarding/flow'` used by the Auto Detect flow --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
ff8f7333c2
commit
fc686f8a6d
44 changed files with 97 additions and 2934 deletions
|
@ -31679,15 +31679,6 @@
|
|||
"xpack.monitoring.updateLicenseButtonLabel": "Mettre à jour la licence",
|
||||
"xpack.monitoring.updateLicenseTitle": "Mettre à jour votre licence",
|
||||
"xpack.monitoring.useAvailableLicenseDescription": "Si vous avez déjà une nouvelle licence, chargez-la maintenant.",
|
||||
"xpack.observability_onboarding.apiKeyBanner.created": "Clé d’API créée.",
|
||||
"xpack.observability_onboarding.apiKeyBanner.created.description": "N’oubliez pas de stocker cette information en lieu sûr. Elle ne sera plus affichée lorsque vous continuerez.",
|
||||
"xpack.observability_onboarding.apiKeyBanner.failed": "Échec de la création de clé d’API.",
|
||||
"xpack.observability_onboarding.apiKeyBanner.failed.description": "Un problème est survenu : {message}",
|
||||
"xpack.observability_onboarding.apiKeyBanner.field.copyButton": "Copier dans le presse-papiers",
|
||||
"xpack.observability_onboarding.apiKeyBanner.field.label": "Clé d'API",
|
||||
"xpack.observability_onboarding.apiKeyBanner.loading": "Création d’une clé d’API",
|
||||
"xpack.observability_onboarding.apiKeyBanner.noPermissions": "L’utilisateur ne dispose pas d’autorisations pour créer une clé d’API.",
|
||||
"xpack.observability_onboarding.apiKeyBanner.noPermissions.description": "Les privilèges de cluster requis sont {requiredClusterPrivileges} et les privilèges d'index requis sont {requiredIndexPrivileges} pour les index {indices}. Veuillez ajouter tous les privilèges requis au rôle de l'utilisateur authentifié.",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.buttonContent": "Réessayer",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.copy": "Certains éléments requis n'ont pas pu être chargés.",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.title": "Échec de chargement",
|
||||
|
@ -31712,28 +31703,8 @@
|
|||
"xpack.observability_onboarding.autoDetectPanel.visualizeYourDataLabel": "Visualiser vos données",
|
||||
"xpack.observability_onboarding.autoDetectPanel.yourDataIsReadyToExploreLabel": "Vos données sont prêtes à l’exploration !",
|
||||
"xpack.observability_onboarding.breadcrumbs.onboarding": "Intégration",
|
||||
"xpack.observability_onboarding.configureLogs.advancedSettings": "Paramètres avancés",
|
||||
"xpack.observability_onboarding.configureLogs.customConfig": "Configurations personnalisées",
|
||||
"xpack.observability_onboarding.configureLogs.customConfig.helper": "Ajoutez des options de configuration YAML à la configuration de votre agent. Faites attention, car l'utilisation de cette fonctionnalité peut endommager votre fichier de configuration. {learnMoreLink}",
|
||||
"xpack.observability_onboarding.configureLogs.description": "Configurer les entrées",
|
||||
"xpack.observability_onboarding.configureLogs.learnMore": "En savoir plus",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.addRow": "Ajouter une ligne",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.helperText": "Vous pouvez utiliser un chemin d'accès ou un modèle de fichier.",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.path": "Chemin de fichier log",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.placeholder": "Exemple : /var/log/application.*",
|
||||
"xpack.observability_onboarding.configureLogs.namespace": "Espace de nom",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.helper": "Ce paramètre modifie le nom du flux de données de l'intégration. {learnMoreLink}",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.placeholder": "Espace de nom",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.tooltip": "Fournir un espace de nom pour personnaliser le groupement de vos logs. Valeur par défaut de l'espace de nom par défaut.",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName": "Nom de service",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.helper": "Nom du service à partir duquel vos données sont collectées.",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.placeholder": "Nommer votre service",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.tooltip": "Fournir un nom de service permet aux services distribués qui tournent sur plusieurs hôtes de mettre en corrélation les instances liées.",
|
||||
"xpack.observability_onboarding.configureLogsContent.euiButtonIcon.deleteLabel": "Supprimer",
|
||||
"xpack.observability_onboarding.configureLogsContent.stepModal.collectCustomLogsLabel": "Collectez des logs personnalisés",
|
||||
"xpack.observability_onboarding.copyToClipboardButton.copyToClipboardButtonLabel": "Copier dans le presse-papiers",
|
||||
"xpack.observability_onboarding.createStackInAWSConsole.createFirehoseStreamInAWSConsoleButtonLabel": "Créer un flux Firehose dans AWS",
|
||||
"xpack.observability_onboarding.customLogs.installShipper.title": "Installer l'agent de transfert pour collecter les logs",
|
||||
"xpack.observability_onboarding.dataIngestStatus.findAllPremadeAssetsTextLabel": "Trouvez toutes les ressources prêtes à l'emploi {viewAllAssetsLink}",
|
||||
"xpack.observability_onboarding.dataIngestStatus.troubleshootingLinkText": "Ouvrir la documentation",
|
||||
"xpack.observability_onboarding.dataIngestStatus.troubleshootingTextLabel": "Vous trouverez plus d'informations et des solutions de résolution des problèmes dans notre documentation. {troubleshootingLink}",
|
||||
|
@ -31800,27 +31771,18 @@
|
|||
"xpack.observability_onboarding.insight.feedbackButtons.negative": "Non",
|
||||
"xpack.observability_onboarding.insight.feedbackButtons.positive": "Oui",
|
||||
"xpack.observability_onboarding.insight.feedbackButtons.title": "Cela a-t-il été utile ?",
|
||||
"xpack.observability_onboarding.inspect.h3.pathLabel": "Chemin",
|
||||
"xpack.observability_onboarding.inspect.h3.stateLabel": "État",
|
||||
"xpack.observability_onboarding.inspect.h3.usageLabel": "Utilisation",
|
||||
"xpack.observability_onboarding.inspect.stepPanel.inspectWizardLabel": "Inspecter l'assistant",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.auto.description": "La configuration agent ci-dessous sera téléchargée par le script d'installation et écrite dans ({configPath}). Ceci écrasera toute configuration agent existante.",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.downloadConfigButton": "Téléchargez le fichier de configuration",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.manual.description": "Ajoutez la configuration suivante à {configPath} sur l'hôte où vous avez installé Elastic Agent.",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.yamlCodeBlockdescription": "Configuration YAML d'Elastic Agent",
|
||||
"xpack.observability_onboarding.installElasticAgent.configureStep.title": "Configurer Elastic Agent",
|
||||
"xpack.observability_onboarding.installElasticAgent.description": "Pour collecter les données depuis votre système et les intégrer à Elastic, vous devez d'abord installer un outil de transfert sur la machine qui génère les logs. Dans ce cas, l'outil de transfert est un agent développé par Elastic.",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig": "Télécharger automatiquement la configuration de l'agent",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig.overwriteWarning": "Le téléchargement automatique de la configuration de l'agent écrase toute configuration d'agent existante chez votre hôte.",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig.tooltip": "Activer pour ajouter une chaîne au bloc de code suivant pour télécharger la configuration standard de l'agent sur votre hôte pendant l'installation. Désactiver pour configurer manuellement l'agent à la prochaine étape.",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform": "Choisissez une plateforme",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.linux": "Linux",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.macOS": "MacOS",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.windows": "Windows",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.description": "Sélectionnez votre plateforme et exécutez la commande install dans votre terminal pour enregistrer, puis démarrez Elastic Agent. Faites ceci pour chaque hôte. Vérifiez {hostRequirementsLink} avant l'installation.",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.hostRequirements": "exigences d'hébergement et autres options d'installation",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.title": "Installation d'Elastic Agent",
|
||||
"xpack.observability_onboarding.installElasticAgent.integrationSuccessCallout.title": "Intégration {integrationName} installée.",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.completedTitle": "La configuration Elastic Agent est écrite dans {configPath}",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.incompleteTitle": "Configurer l'agent",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.loadingTitle": "Téléchargement de la configuration Elastic Agent",
|
||||
|
@ -31836,9 +31798,6 @@
|
|||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.completedTitle": "Connecté à Elastic Agent",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.incompleteTitle": "Se connecter à Elastic Agent",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.loadingTitle": "Connexion à Elastic Agent",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.completedTitle": "Les logs sont en cours de transfert.",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.incompleteTitle": "Transfert des logs dans Elastic Observability",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.loadingTitle": "En attente du transfert des logs…",
|
||||
"xpack.observability_onboarding.installElasticAgent.troubleshooting": "Résolution des problèmes",
|
||||
"xpack.observability_onboarding.installIntegration.error.unauthorized": "Le privilège Kibana {requiredKibanaPrivileges} requis est manquant. Veuillez ajouter le privilège requis au rôle de l'utilisateur authentifié.",
|
||||
"xpack.observability_onboarding.installOtelCollector.configStep.copyCommand": "Copier dans le presse-papiers",
|
||||
|
@ -31898,7 +31857,6 @@
|
|||
"xpack.observability_onboarding.packageList.uploadFileTitle": "Charger un fichier",
|
||||
"xpack.observability_onboarding.progressCallout.li.otherLabel": "Autres (les logs non pris en charge seront stockés dans un index Firehose générique).",
|
||||
"xpack.observability_onboarding.progressCallout.strong.allServicesWeCanLabel": "Tous les services que nous pouvons détecter",
|
||||
"xpack.observability_onboarding.steps.exploreLogs": "Explorer les logs",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmDescription": "Collectez des traces distribuées à partir de vos applications avec Elastic APM",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmOtelDescription": "Collectez des traces distribuées avec OpenTelemetry",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmOtelTitle": "OpenTelemetry",
|
||||
|
|
|
@ -31658,15 +31658,6 @@
|
|||
"xpack.monitoring.updateLicenseButtonLabel": "ライセンスを更新",
|
||||
"xpack.monitoring.updateLicenseTitle": "ライセンスの更新",
|
||||
"xpack.monitoring.useAvailableLicenseDescription": "すでに新しいライセンスがある場合は、今すぐアップロードしてください。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.created": "APIキーが作成されました。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.created.description": "必ずこの情報を安全な場所に保管してください。続行すると、表示されなくなります。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.failed": "APIキーを作成できませんでした。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.failed.description": "問題が発生しました:{message}",
|
||||
"xpack.observability_onboarding.apiKeyBanner.field.copyButton": "クリップボードにコピー",
|
||||
"xpack.observability_onboarding.apiKeyBanner.field.label": "APIキー",
|
||||
"xpack.observability_onboarding.apiKeyBanner.loading": "APIキーを作成中",
|
||||
"xpack.observability_onboarding.apiKeyBanner.noPermissions": "ユーザーにはAPIキーを作成する権限がありません。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.noPermissions.description": "必要なクラスター特権は{requiredClusterPrivileges}です。インデックス{indices}で必要なインデックス特権は{requiredIndexPrivileges}です。認証されたユーザーのロールにすべての必要な特権を追加してください。",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.buttonContent": "再試行",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.copy": "一部の必要な要素を読み込めませんでした。",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.title": "読み込み失敗",
|
||||
|
@ -31691,28 +31682,8 @@
|
|||
"xpack.observability_onboarding.autoDetectPanel.visualizeYourDataLabel": "データを可視化する",
|
||||
"xpack.observability_onboarding.autoDetectPanel.yourDataIsReadyToExploreLabel": "データを探索できます!",
|
||||
"xpack.observability_onboarding.breadcrumbs.onboarding": "オンボーディング",
|
||||
"xpack.observability_onboarding.configureLogs.advancedSettings": "高度な設定",
|
||||
"xpack.observability_onboarding.configureLogs.customConfig": "カスタム構成",
|
||||
"xpack.observability_onboarding.configureLogs.customConfig.helper": "エージェント構成にYAML構成オプションを追加します。この機能を使用すると、構成ファイルが破損する可能性があるため、注意してください。{learnMoreLink}",
|
||||
"xpack.observability_onboarding.configureLogs.description": "入力を構成",
|
||||
"xpack.observability_onboarding.configureLogs.learnMore": "詳細",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.addRow": "行の追加",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.helperText": "ファイルパスまたはパターンを使用できます。",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.path": "ログファイルパス",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.placeholder": "例:/var/log/application.*",
|
||||
"xpack.observability_onboarding.configureLogs.namespace": "名前空間",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.helper": "この設定により、統合のデータストリームの名前が変更されます。{learnMoreLink}",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.placeholder": "名前空間",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.tooltip": "名前空間を指定して、ログのグループ化をカスタマイズします。デフォルト名前空間を設定します。",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName": "サービス名",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.helper": "データが収集されるサービスの名前を設定します。",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.placeholder": "サービス名を指定",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.tooltip": "複数のホスト上で実行される分散サービスが関連するインスタンスを関連付けることができるように、サービス名を指定します。",
|
||||
"xpack.observability_onboarding.configureLogsContent.euiButtonIcon.deleteLabel": "削除",
|
||||
"xpack.observability_onboarding.configureLogsContent.stepModal.collectCustomLogsLabel": "カスタムログを収集",
|
||||
"xpack.observability_onboarding.copyToClipboardButton.copyToClipboardButtonLabel": "クリップボードにコピー",
|
||||
"xpack.observability_onboarding.createStackInAWSConsole.createFirehoseStreamInAWSConsoleButtonLabel": "AWSでFirehose Streamを作成",
|
||||
"xpack.observability_onboarding.customLogs.installShipper.title": "ログを収集するためのシッパーをインストール",
|
||||
"xpack.observability_onboarding.dataIngestStatus.findAllPremadeAssetsTextLabel": "{viewAllAssetsLink}ですぐに使えるすべての組み込みのアセットをご覧ください",
|
||||
"xpack.observability_onboarding.dataIngestStatus.troubleshootingLinkText": "ドキュメントを開く",
|
||||
"xpack.observability_onboarding.dataIngestStatus.troubleshootingTextLabel": "詳細とトラブルシューティングの解決策については、ドキュメントをご覧ください。{troubleshootingLink}",
|
||||
|
@ -31779,27 +31750,18 @@
|
|||
"xpack.observability_onboarding.insight.feedbackButtons.negative": "いいえ",
|
||||
"xpack.observability_onboarding.insight.feedbackButtons.positive": "はい",
|
||||
"xpack.observability_onboarding.insight.feedbackButtons.title": "役に立ちましたか。",
|
||||
"xpack.observability_onboarding.inspect.h3.pathLabel": "パス",
|
||||
"xpack.observability_onboarding.inspect.h3.stateLabel": "ステータス",
|
||||
"xpack.observability_onboarding.inspect.h3.usageLabel": "使用方法",
|
||||
"xpack.observability_onboarding.inspect.stepPanel.inspectWizardLabel": "検査ウィザード",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.auto.description": "次のエージェント構成が、インストールスクリプトによってダウンロードされ、({configPath})に書き込まれます。これにより、既存のエージェント構成がすべて上書きされます。",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.downloadConfigButton": "構成ファイルのダウンロード",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.manual.description": "Elasticエージェントをインストールしたホストの{configPath}に以下の構成を追加します。",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.yamlCodeBlockdescription": "Elasticエージェントyaml構成",
|
||||
"xpack.observability_onboarding.installElasticAgent.configureStep.title": "Elasticエージェントの構成",
|
||||
"xpack.observability_onboarding.installElasticAgent.description": "システムからデータを収集してElasticにストリーミングするには、まずログを生成するコンピューターでシッピングツールをインストールする必要があります。この場合、シッピングツールはElasticが開発したエージェントです。",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig": "エージェント構成を自動的にダウンロード",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig.overwriteWarning": "エージェント構成を自動的にダウンロードすると、ホスト上の既存のエージェント構成が上書きされます。",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig.tooltip": "オンにすると、インストール中にエージェントの標準構成をホストにダウンロードする以下のコードブロックに文字列が追加されます。オフにすると、次のステップでエージェントを手動で構成することができます。",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform": "プラットフォームを選択",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.linux": "Linux",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.macOS": "MacOS",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.windows": "Windows",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.description": "プラットフォームを選択し、ターミナルでinstallコマンドを実行してElasticエージェントを登録、起動します。各ホストでこの手順を実行します。インストール前に{hostRequirementsLink}を確認してください。",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.hostRequirements": "ホスト要件とその他のインストールオプション",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.title": "Elasticエージェントをインストール",
|
||||
"xpack.observability_onboarding.installElasticAgent.integrationSuccessCallout.title": "{integrationName}統合がインストールされました。",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.completedTitle": "Elasticエージェント構成が{configPath}に書き込まれました",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.incompleteTitle": "エージェントの構成",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.loadingTitle": "Elasticエージェント構成をダウンロード中",
|
||||
|
@ -31815,9 +31777,6 @@
|
|||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.completedTitle": "Elasticエージェントに接続しました",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.incompleteTitle": "Elasticエージェントに接続",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.loadingTitle": "Elasticエージェントに接続中",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.completedTitle": "ログを送信中です。",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.incompleteTitle": "Elasticオブザーバビリティにログを送信",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.loadingTitle": "ログの送信を待機中...",
|
||||
"xpack.observability_onboarding.installElasticAgent.troubleshooting": "トラブルシューティング",
|
||||
"xpack.observability_onboarding.installIntegration.error.unauthorized": "必要なkibana権限{requiredKibanaPrivileges}がありません。認証されたユーザーのロールに必要な権限を追加してください。",
|
||||
"xpack.observability_onboarding.installOtelCollector.configStep.copyCommand": "クリップボードにコピー",
|
||||
|
@ -31877,7 +31836,6 @@
|
|||
"xpack.observability_onboarding.packageList.uploadFileTitle": "ファイルをアップロード",
|
||||
"xpack.observability_onboarding.progressCallout.li.otherLabel": "その他(サポートされていないログは、一般的なFirehoseインデックスに格納されます)。",
|
||||
"xpack.observability_onboarding.progressCallout.strong.allServicesWeCanLabel": "検出可能なすべてのサービス",
|
||||
"xpack.observability_onboarding.steps.exploreLogs": "ログを探索",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmDescription": "Elastic APMを使用してアプリケーションから分散トレースを収集",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmOtelDescription": "OpenTelemetryで分散トレースを収集",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmOtelTitle": "OpenTelemetry",
|
||||
|
|
|
@ -31713,15 +31713,6 @@
|
|||
"xpack.monitoring.updateLicenseButtonLabel": "更新许可证",
|
||||
"xpack.monitoring.updateLicenseTitle": "更新您的许可证",
|
||||
"xpack.monitoring.useAvailableLicenseDescription": "如果您已经持有新的许可证,请立即上传。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.created": "已创建 API 密钥。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.created.description": "记得将此信息存储在安全位置。在您继续后,将不再显示该信息。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.failed": "无法创建 API 密钥。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.failed.description": "出现问题:{message}",
|
||||
"xpack.observability_onboarding.apiKeyBanner.field.copyButton": "复制到剪贴板",
|
||||
"xpack.observability_onboarding.apiKeyBanner.field.label": "API 密钥",
|
||||
"xpack.observability_onboarding.apiKeyBanner.loading": "正在创建 API 密钥",
|
||||
"xpack.observability_onboarding.apiKeyBanner.noPermissions": "用户无权创建 API 密钥。",
|
||||
"xpack.observability_onboarding.apiKeyBanner.noPermissions.description": "索引 {indices} 的所需集群权限为 {requiredClusterPrivileges},所需索引权限为 {requiredIndexPrivileges},请为已通过身份验证的用户角色添加所有所需权限。",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.buttonContent": "重试",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.copy": "无法加载某些必需元素。",
|
||||
"xpack.observability_onboarding.asyncLoadFailureCallout.title": "加载失败",
|
||||
|
@ -31746,28 +31737,8 @@
|
|||
"xpack.observability_onboarding.autoDetectPanel.visualizeYourDataLabel": "可视化数据",
|
||||
"xpack.observability_onboarding.autoDetectPanel.yourDataIsReadyToExploreLabel": "数据已准确就绪,可供浏览!",
|
||||
"xpack.observability_onboarding.breadcrumbs.onboarding": "载入",
|
||||
"xpack.observability_onboarding.configureLogs.advancedSettings": "高级设置",
|
||||
"xpack.observability_onboarding.configureLogs.customConfig": "定制配置",
|
||||
"xpack.observability_onboarding.configureLogs.customConfig.helper": "将 YAML 配置选项添加到代理配置。请务必谨慎使用此功能,因为它可能会破坏配置文件。{learnMoreLink}",
|
||||
"xpack.observability_onboarding.configureLogs.description": "配置输入",
|
||||
"xpack.observability_onboarding.configureLogs.learnMore": "了解详情",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.addRow": "添加行",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.helperText": "可以使用文件路径或模式。",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.path": "日志文件路径",
|
||||
"xpack.observability_onboarding.configureLogs.logFile.placeholder": "示例:/var/log/application.*",
|
||||
"xpack.observability_onboarding.configureLogs.namespace": "命名空间",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.helper": "此设置将更改集成的数据流的名称。{learnMoreLink}",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.placeholder": "命名空间",
|
||||
"xpack.observability_onboarding.configureLogs.namespace.tooltip": "提供命名空间以定制日志分组。默认采用默认命名空间。",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName": "服务名称",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.helper": "命名将从中收集数据的服务。",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.placeholder": "为服务提供名称",
|
||||
"xpack.observability_onboarding.configureLogs.serviceName.tooltip": "提供服务名称以便在多个主机上运行的分布式服务关联相关实例。",
|
||||
"xpack.observability_onboarding.configureLogsContent.euiButtonIcon.deleteLabel": "删除",
|
||||
"xpack.observability_onboarding.configureLogsContent.stepModal.collectCustomLogsLabel": "收集定制日志",
|
||||
"xpack.observability_onboarding.copyToClipboardButton.copyToClipboardButtonLabel": "复制到剪贴板",
|
||||
"xpack.observability_onboarding.createStackInAWSConsole.createFirehoseStreamInAWSConsoleButtonLabel": "在 AWS 中创建 Firehose 流",
|
||||
"xpack.observability_onboarding.customLogs.installShipper.title": "安装采集器以收集日志",
|
||||
"xpack.observability_onboarding.dataIngestStatus.findAllPremadeAssetsTextLabel": "查找所有可随时使用 {viewAllAssetsLink} 的现成资产",
|
||||
"xpack.observability_onboarding.dataIngestStatus.troubleshootingLinkText": "打开文档",
|
||||
"xpack.observability_onboarding.dataIngestStatus.troubleshootingTextLabel": "在我们的文档中查找更多详情和故障排除解决方案。{troubleshootingLink}",
|
||||
|
@ -31834,27 +31805,18 @@
|
|||
"xpack.observability_onboarding.insight.feedbackButtons.negative": "否",
|
||||
"xpack.observability_onboarding.insight.feedbackButtons.positive": "是",
|
||||
"xpack.observability_onboarding.insight.feedbackButtons.title": "这是否有帮助?",
|
||||
"xpack.observability_onboarding.inspect.h3.pathLabel": "路径",
|
||||
"xpack.observability_onboarding.inspect.h3.stateLabel": "状态",
|
||||
"xpack.observability_onboarding.inspect.h3.usageLabel": "用法",
|
||||
"xpack.observability_onboarding.inspect.stepPanel.inspectWizardLabel": "检查向导",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.auto.description": "以下代理配置将由安装脚本下载并写入到 ({configPath})。这会覆盖任何现有代理配置。",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.downloadConfigButton": "下载配置文件",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.manual.description": "将以下配置添加到已安装 Elastic 代理的主机上的{configPath}。",
|
||||
"xpack.observability_onboarding.installElasticAgent.configStep.yamlCodeBlockdescription": "Elastic 代理 yaml 配置",
|
||||
"xpack.observability_onboarding.installElasticAgent.configureStep.title": "配置 Elastic 代理",
|
||||
"xpack.observability_onboarding.installElasticAgent.description": "要从您的系统收集数据并将其流式传输到 Elastic,您首先需要在生成日志的机器上安装传输工具。在此情况下,传输工具为由 Elastic 开发的代理。",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig": "自动下载代理的配置",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig.overwriteWarning": "自动下载代理配置将覆盖您主机上的任何现有代理配置。",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig.tooltip": "打开可将一个字符串添加到以下代码块,该代码会在安装期间将代理的标准配置下载到您的主机上。关闭可在下一步中手动配置代理。",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform": "选择平台",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.linux": "Linux",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.macOS": "MacOS",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.windows": "Windows",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.description": "选择平台并在终端中运行安装命令,以注册并启动 Elastic 代理。对每台主机执行此操作。请在安装之前复查{hostRequirementsLink}。",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.hostRequirements": "主机要求和其他安装选项",
|
||||
"xpack.observability_onboarding.installElasticAgent.installStep.title": "安装 Elastic 代理",
|
||||
"xpack.observability_onboarding.installElasticAgent.integrationSuccessCallout.title": "已安装 {integrationName} 集成。",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.completedTitle": "Elastic 代理配置已写入到 {configPath}",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.incompleteTitle": "配置代理",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaConfig.loadingTitle": "正在下载 Elastic 代理配置",
|
||||
|
@ -31870,9 +31832,6 @@
|
|||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.completedTitle": "已连接到 Elastic 代理",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.incompleteTitle": "连接到 Elastic 代理",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.eaStatus.loadingTitle": "正在连接 Elastic 代理",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.completedTitle": "正在传输日志!",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.incompleteTitle": "传输日志到 Elastic Observability",
|
||||
"xpack.observability_onboarding.installElasticAgent.progress.logsIngest.loadingTitle": "等待传输日志......",
|
||||
"xpack.observability_onboarding.installElasticAgent.troubleshooting": "故障排除",
|
||||
"xpack.observability_onboarding.installIntegration.error.unauthorized": "缺失所需的 Kibana 权限 {requiredKibanaPrivileges},请将所需权限添加到已通过身份验证的用户的角色。",
|
||||
"xpack.observability_onboarding.installOtelCollector.configStep.copyCommand": "复制到剪贴板",
|
||||
|
@ -31932,7 +31891,6 @@
|
|||
"xpack.observability_onboarding.packageList.uploadFileTitle": "上传文件",
|
||||
"xpack.observability_onboarding.progressCallout.li.otherLabel": "其他(不受支持的日志将存储在常规 Firehose 索引中)。",
|
||||
"xpack.observability_onboarding.progressCallout.strong.allServicesWeCanLabel": "我们可以检测的所有服务",
|
||||
"xpack.observability_onboarding.steps.exploreLogs": "浏览日志",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmDescription": "使用 Elastic APM 从您的应用程序中收集分布式跟踪",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmOtelDescription": "使用 OpenTelemetry 收集分布式跟踪",
|
||||
"xpack.observability_onboarding.useCustomCardsForCategory.apmOtelTitle": "OpenTelemetry",
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`generateCustomLogsYml should return a basic yml configuration 1`] = `
|
||||
"outputs:
|
||||
default:
|
||||
type: elasticsearch
|
||||
hosts:
|
||||
- http://localhost:9200
|
||||
api_key: elastic:changeme
|
||||
inputs:
|
||||
- id: my-logs-id
|
||||
type: logfile
|
||||
data_stream:
|
||||
namespace: default
|
||||
streams:
|
||||
- id: logs-onboarding-my-dataset
|
||||
data_stream:
|
||||
dataset: my-dataset
|
||||
paths:
|
||||
- /my-service.logs
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`generateCustomLogsYml should return a yml configuration with customConfigurations 1`] = `
|
||||
"outputs:
|
||||
default:
|
||||
type: elasticsearch
|
||||
hosts:
|
||||
- http://localhost:9200
|
||||
api_key: elastic:changeme
|
||||
inputs:
|
||||
- id: my-logs-id
|
||||
type: logfile
|
||||
data_stream:
|
||||
namespace: default
|
||||
streams:
|
||||
- id: logs-onboarding-my-dataset
|
||||
data_stream:
|
||||
dataset: my-dataset
|
||||
paths:
|
||||
- /my-service.logs
|
||||
agent.retry:
|
||||
enabled: true
|
||||
retriesCount: 3
|
||||
agent.monitoring:
|
||||
metrics: false
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`generateCustomLogsYml should return a yml configuration with multiple logFilePaths 1`] = `
|
||||
"outputs:
|
||||
default:
|
||||
type: elasticsearch
|
||||
hosts:
|
||||
- http://localhost:9200
|
||||
api_key: elastic:changeme
|
||||
inputs:
|
||||
- id: my-logs-id
|
||||
type: logfile
|
||||
data_stream:
|
||||
namespace: default
|
||||
streams:
|
||||
- id: logs-onboarding-my-dataset
|
||||
data_stream:
|
||||
dataset: my-dataset
|
||||
paths:
|
||||
- /my-service-1.logs
|
||||
- /my-service-2.logs
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`generateCustomLogsYml should return a yml configuration with service name 1`] = `
|
||||
"outputs:
|
||||
default:
|
||||
type: elasticsearch
|
||||
hosts:
|
||||
- http://localhost:9200
|
||||
api_key: elastic:changeme
|
||||
inputs:
|
||||
- id: my-logs-id
|
||||
type: logfile
|
||||
data_stream:
|
||||
namespace: default
|
||||
streams:
|
||||
- id: logs-onboarding-my-dataset
|
||||
data_stream:
|
||||
dataset: my-dataset
|
||||
paths:
|
||||
- /my-service.logs
|
||||
processors:
|
||||
- add_fields:
|
||||
target: service
|
||||
fields:
|
||||
name: my-service
|
||||
"
|
||||
`;
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* 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 { dump } from 'js-yaml';
|
||||
import { generateCustomLogsYml } from './generate_custom_logs_yml';
|
||||
|
||||
const baseMockConfig = {
|
||||
datasetName: 'my-dataset',
|
||||
namespace: 'default',
|
||||
logFilePaths: ['/my-service.logs'],
|
||||
apiKey: 'elastic:changeme',
|
||||
esHost: ['http://localhost:9200'],
|
||||
logfileId: 'my-logs-id',
|
||||
};
|
||||
|
||||
describe('generateCustomLogsYml', () => {
|
||||
it('should return a basic yml configuration', () => {
|
||||
const result = generateCustomLogsYml(baseMockConfig);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should return a yml configuration with multiple logFilePaths', () => {
|
||||
const mockConfig = {
|
||||
...baseMockConfig,
|
||||
logFilePaths: ['/my-service-1.logs', '/my-service-2.logs'],
|
||||
};
|
||||
|
||||
const result = generateCustomLogsYml(mockConfig);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should return a yml configuration with service name', () => {
|
||||
const mockConfig = {
|
||||
...baseMockConfig,
|
||||
serviceName: 'my-service',
|
||||
};
|
||||
|
||||
const result = generateCustomLogsYml(mockConfig);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should return a yml configuration with customConfigurations', () => {
|
||||
const mockConfig = {
|
||||
...baseMockConfig,
|
||||
customConfigurations: dump({
|
||||
['agent.retry']: {
|
||||
enabled: true,
|
||||
retriesCount: 3,
|
||||
},
|
||||
['agent.monitoring']: {
|
||||
metrics: false,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
const result = generateCustomLogsYml(mockConfig);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* 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 { dump, load } from 'js-yaml';
|
||||
|
||||
export const generateCustomLogsYml = ({
|
||||
datasetName = '',
|
||||
serviceName,
|
||||
namespace = '',
|
||||
customConfigurations,
|
||||
logFilePaths = [],
|
||||
apiKey,
|
||||
esHost,
|
||||
logfileId,
|
||||
}: {
|
||||
datasetName?: string;
|
||||
serviceName?: string;
|
||||
namespace?: string;
|
||||
customConfigurations?: string;
|
||||
logFilePaths?: string[];
|
||||
apiKey: string;
|
||||
esHost: string[];
|
||||
logfileId: string;
|
||||
}) => {
|
||||
const customConfigYaml = load(customConfigurations ?? '');
|
||||
const processors = [
|
||||
{
|
||||
add_fields: {
|
||||
target: 'service',
|
||||
fields: {
|
||||
name: serviceName,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return dump({
|
||||
...{
|
||||
outputs: {
|
||||
default: {
|
||||
type: 'elasticsearch',
|
||||
hosts: esHost,
|
||||
api_key: apiKey,
|
||||
},
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
id: logfileId,
|
||||
type: 'logfile',
|
||||
data_stream: {
|
||||
namespace,
|
||||
},
|
||||
streams: [
|
||||
{
|
||||
id: `logs-onboarding-${datasetName}`,
|
||||
data_stream: {
|
||||
dataset: datasetName,
|
||||
},
|
||||
paths: logFilePaths,
|
||||
...(serviceName ? { processors } : {}),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
...customConfigYaml,
|
||||
});
|
||||
};
|
|
@ -1,8 +0,0 @@
|
|||
/*
|
||||
* 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 * from './custom_logs/generate_custom_logs_yml';
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* 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 type EaInstallProgressStepId =
|
||||
| 'ea-download'
|
||||
| 'ea-extract'
|
||||
| 'ea-install'
|
||||
| 'ea-status'
|
||||
| 'ea-config';
|
||||
|
||||
export type LogsFlowProgressStepId = EaInstallProgressStepId | 'logs-ingest';
|
|
@ -35,7 +35,7 @@ export const OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT: ObservabilityOnboardingTe
|
|||
type: 'keyword',
|
||||
_meta: {
|
||||
description:
|
||||
"The current onboarding flow type user is going through (e.g. 'autoDetect', 'logFiles', 'kubernetes'). If not present, user is on the landing screen.",
|
||||
"The current onboarding flow type user is going through (e.g. 'autoDetect', 'kubernetes'). If not present, user is on the landing screen.",
|
||||
},
|
||||
},
|
||||
flow_id: {
|
||||
|
|
|
@ -12,7 +12,6 @@ import { useLocation } from 'react-router-dom-v5-compat';
|
|||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
AutoDetectPage,
|
||||
CustomLogsPage,
|
||||
KubernetesPage,
|
||||
LandingPage,
|
||||
OtelLogsPage,
|
||||
|
@ -44,9 +43,6 @@ export function ObservabilityOnboardingFlow() {
|
|||
<Route path="/auto-detect">
|
||||
<AutoDetectPage />
|
||||
</Route>
|
||||
<Route path="/customLogs">
|
||||
<CustomLogsPage />
|
||||
</Route>
|
||||
<Route path="/kubernetes">
|
||||
<KubernetesPage />
|
||||
</Route>
|
||||
|
|
|
@ -39,7 +39,6 @@ export function useCustomCards(
|
|||
history,
|
||||
`/otel-kubernetes/${location.search}`
|
||||
);
|
||||
const { href: customLogsUrl } = reactRouterNavigate(history, `/customLogs/${location.search}`);
|
||||
const { href: firehoseUrl } = reactRouterNavigate(history, `/firehose/${location.search}`);
|
||||
|
||||
const apmUrl = `${getUrlForApp?.('apm')}/${isServerless ? 'onboarding' : 'tutorial'}`;
|
||||
|
@ -393,23 +392,6 @@ export function useCustomCards(
|
|||
integration: '',
|
||||
isCollectionCard: false,
|
||||
},
|
||||
{
|
||||
id: 'custom-logs',
|
||||
type: 'virtual',
|
||||
title: 'Stream log files',
|
||||
description: 'Stream any logs into Elastic in a simple way and explore their data',
|
||||
name: 'custom-logs-virtual',
|
||||
categories: ['observability'],
|
||||
icons: [
|
||||
{
|
||||
type: 'eui',
|
||||
src: 'filebeatApp',
|
||||
},
|
||||
],
|
||||
url: customLogsUrl,
|
||||
version: '',
|
||||
integration: '',
|
||||
},
|
||||
/**
|
||||
* The new Firehose card should only be visible on Cloud
|
||||
* as Firehose integration requires additional proxy,
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { PageTemplate } from './template';
|
||||
import { BackButton } from '../shared/back_button';
|
||||
import { CustomLogsPanel } from '../quickstart_flows/custom_logs';
|
||||
|
||||
export const CustomLogsPage = () => (
|
||||
<PageTemplate>
|
||||
<BackButton />
|
||||
<CustomLogsPanel />
|
||||
</PageTemplate>
|
||||
);
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
export { AutoDetectPage } from './auto_detect';
|
||||
export { CustomLogsPage } from './custom_logs';
|
||||
export { KubernetesPage } from './kubernetes';
|
||||
export { OtelKubernetesPage } from './otel_kubernetes';
|
||||
export { LandingPage } from './landing';
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
EuiButtonIcon,
|
||||
EuiCallOut,
|
||||
EuiCopy,
|
||||
EuiFieldText,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiLoadingSpinner,
|
||||
} from '@elastic/eui';
|
||||
import { IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FETCH_STATUS } from '@kbn/observability-shared-plugin/public';
|
||||
import React from 'react';
|
||||
import { APIReturnType } from '../../../services/rest/create_call_api';
|
||||
|
||||
type ApiKeyPayload = APIReturnType<'POST /internal/observability_onboarding/logs/flow'>;
|
||||
|
||||
export type HasPrivileges = boolean;
|
||||
|
||||
export function ApiKeyBanner({
|
||||
hasPrivileges = true,
|
||||
status,
|
||||
payload,
|
||||
error,
|
||||
}: {
|
||||
hasPrivileges?: boolean;
|
||||
status: FETCH_STATUS;
|
||||
payload?: Partial<ApiKeyPayload>;
|
||||
error?: IHttpFetchError<ResponseErrorBody>;
|
||||
}) {
|
||||
const loadingCallout = (
|
||||
<EuiCallOut
|
||||
title={
|
||||
<EuiFlexGroup alignItems="center" gutterSize="m">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiLoadingSpinner size="m" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
{i18n.translate('xpack.observability_onboarding.apiKeyBanner.loading', {
|
||||
defaultMessage: 'Creating API Key',
|
||||
})}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
color="primary"
|
||||
data-test-subj="obltOnboardingLogsCreatingApiKey"
|
||||
/>
|
||||
);
|
||||
|
||||
const apiKeySuccessCallout = (
|
||||
<EuiCallOut
|
||||
title={i18n.translate('xpack.observability_onboarding.apiKeyBanner.created', {
|
||||
defaultMessage: 'API Key created.',
|
||||
})}
|
||||
color="success"
|
||||
iconType="check"
|
||||
data-test-subj="obltOnboardingLogsApiKeyCreated"
|
||||
>
|
||||
<p>
|
||||
{i18n.translate('xpack.observability_onboarding.apiKeyBanner.created.description', {
|
||||
defaultMessage:
|
||||
'Remember to store this information in a safe place. It won’t be displayed anymore after you continue.',
|
||||
})}
|
||||
</p>
|
||||
<EuiFieldText
|
||||
data-test-subj="apmAgentKeyCallOutFieldText"
|
||||
readOnly
|
||||
value={payload?.apiKeyEncoded}
|
||||
aria-label={i18n.translate('xpack.observability_onboarding.apiKeyBanner.field.label', {
|
||||
defaultMessage: 'Api Key',
|
||||
})}
|
||||
append={
|
||||
<EuiCopy textToCopy={payload?.apiKeyEncoded ?? ''}>
|
||||
{(copy) => (
|
||||
<EuiButtonIcon
|
||||
data-test-subj="observabilityOnboardingApiKeySuccessCalloutButton"
|
||||
iconType="copyClipboard"
|
||||
onClick={copy}
|
||||
color="primary"
|
||||
css={{
|
||||
'> svg.euiIcon': {
|
||||
borderRadius: '0 !important',
|
||||
},
|
||||
}}
|
||||
aria-label={i18n.translate(
|
||||
'xpack.observability_onboarding.apiKeyBanner.field.copyButton',
|
||||
{
|
||||
defaultMessage: 'Copy to clipboard',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</EuiCopy>
|
||||
}
|
||||
/>
|
||||
</EuiCallOut>
|
||||
);
|
||||
|
||||
const apiKeyFailureCallout = (
|
||||
<EuiCallOut
|
||||
title={i18n.translate('xpack.observability_onboarding.apiKeyBanner.failed', {
|
||||
defaultMessage: 'Failed to create API key.',
|
||||
})}
|
||||
color="danger"
|
||||
iconType="error"
|
||||
data-test-subj="obltOnboardingLogsApiKeyCreationFailed"
|
||||
>
|
||||
<p>
|
||||
{i18n.translate('xpack.observability_onboarding.apiKeyBanner.failed.description', {
|
||||
defaultMessage: 'Something went wrong: {message}',
|
||||
values: {
|
||||
message: error?.body?.message,
|
||||
},
|
||||
})}
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
);
|
||||
|
||||
const noPermissionsCallout = (
|
||||
<EuiCallOut
|
||||
title={i18n.translate('xpack.observability_onboarding.apiKeyBanner.noPermissions', {
|
||||
defaultMessage: 'User does not have permissions to create API key.',
|
||||
})}
|
||||
color="warning"
|
||||
iconType="warning"
|
||||
data-test-subj="obltOnboardingLogsApiKeyCreationNoPrivileges"
|
||||
>
|
||||
<p>
|
||||
{i18n.translate('xpack.observability_onboarding.apiKeyBanner.noPermissions.description', {
|
||||
defaultMessage:
|
||||
'Required cluster privileges are {requiredClusterPrivileges} and required index privileges are {requiredIndexPrivileges} for indices {indices}, please add all required privileges to the role of the authenticated user.',
|
||||
values: {
|
||||
requiredClusterPrivileges: "['monitor', 'manage_own_api_key']",
|
||||
requiredIndexPrivileges: "['auto_configure', 'create_doc']",
|
||||
indices: "['logs-*-*', 'metrics-*-*']",
|
||||
},
|
||||
})}
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
);
|
||||
|
||||
if (!hasPrivileges) {
|
||||
return noPermissionsCallout;
|
||||
}
|
||||
|
||||
if (status === FETCH_STATUS.SUCCESS) {
|
||||
return apiKeySuccessCallout;
|
||||
}
|
||||
|
||||
if (status === FETCH_STATUS.FAILURE) {
|
||||
return apiKeyFailureCallout;
|
||||
}
|
||||
|
||||
return loadingCallout;
|
||||
}
|
|
@ -1,402 +0,0 @@
|
|||
/*
|
||||
* 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 {
|
||||
EuiAccordion,
|
||||
EuiButtonEmpty,
|
||||
EuiButtonIcon,
|
||||
EuiFieldText,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiText,
|
||||
EuiForm,
|
||||
EuiFormRow,
|
||||
EuiHorizontalRule,
|
||||
EuiIconTip,
|
||||
EuiLink,
|
||||
EuiSpacer,
|
||||
EuiTextArea,
|
||||
useEuiFontSize,
|
||||
useEuiTheme,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import {
|
||||
ConnectedCustomIntegrationsButton,
|
||||
ConnectedCustomIntegrationsForm,
|
||||
useConsumerCustomIntegrations,
|
||||
CustomIntegrationsProvider,
|
||||
Callbacks,
|
||||
} from '@kbn/custom-integrations';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { useWizard } from '.';
|
||||
import { OptionalFormRow } from '../shared/optional_form_row';
|
||||
import { StepModal } from '../shared/step_panel';
|
||||
import { getFilename } from './get_filename';
|
||||
|
||||
const customIntegrationsTestSubjects = {
|
||||
create: {
|
||||
integrationName: 'obltOnboardingCustomLogsIntegrationsName',
|
||||
datasetName: 'obltOnboardingCustomLogsDatasetName',
|
||||
errorCallout: {
|
||||
callout: 'obltOnboardingCustomIntegrationErrorCallout',
|
||||
},
|
||||
},
|
||||
button: 'obltOnboardingCustomLogsContinue',
|
||||
};
|
||||
|
||||
export function ConfigureLogs() {
|
||||
const {
|
||||
services: { http },
|
||||
} = useKibana();
|
||||
|
||||
const { goToStep, setState, getState } = useWizard();
|
||||
const { integrationName, datasetName, lastCreatedIntegrationOptions } = getState();
|
||||
|
||||
const onIntegrationCreation: Callbacks['onIntegrationCreation'] = (integrationOptions) => {
|
||||
const { integrationName: createdIntegrationName, datasets: createdDatasets } =
|
||||
integrationOptions;
|
||||
setState((state) => ({
|
||||
...state,
|
||||
integrationName: createdIntegrationName,
|
||||
datasetName: createdDatasets[0].name,
|
||||
lastCreatedIntegrationOptions: integrationOptions,
|
||||
}));
|
||||
goToStep('installElasticAgent');
|
||||
};
|
||||
|
||||
return (
|
||||
<CustomIntegrationsProvider
|
||||
services={{ http }}
|
||||
onIntegrationCreation={onIntegrationCreation}
|
||||
initialState={{
|
||||
mode: 'create',
|
||||
context: {
|
||||
options: {
|
||||
deletePrevious: true,
|
||||
resetOnCreation: false,
|
||||
errorOnFailedCleanup: false,
|
||||
},
|
||||
...(integrationName !== undefined && datasetName !== undefined
|
||||
? {
|
||||
fields: {
|
||||
integrationName,
|
||||
datasets: [{ name: datasetName, type: 'logs' as const }],
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
previouslyCreatedIntegration: lastCreatedIntegrationOptions,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ConfigureLogsContent />
|
||||
</CustomIntegrationsProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export function ConfigureLogsContent() {
|
||||
const {
|
||||
dispatchableEvents: { updateCreateFields },
|
||||
} = useConsumerCustomIntegrations();
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const xsFontSize = useEuiFontSize('xs').fontSize;
|
||||
|
||||
const { getState, setState } = useWizard();
|
||||
const wizardState = getState();
|
||||
const [serviceName, setServiceName] = useState(wizardState.serviceName);
|
||||
const [logFilePaths, setLogFilePaths] = useState(wizardState.logFilePaths);
|
||||
const [namespace, setNamespace] = useState(wizardState.namespace);
|
||||
const [customConfigurations, setCustomConfigurations] = useState(
|
||||
wizardState.customConfigurations
|
||||
);
|
||||
const logFilePathNotConfigured = logFilePaths.every((filepath) => !filepath);
|
||||
|
||||
const onContinue = useCallback(() => {
|
||||
setState((state) => ({
|
||||
...state,
|
||||
serviceName,
|
||||
logFilePaths: logFilePaths.filter((filepath) => !!filepath),
|
||||
namespace,
|
||||
customConfigurations,
|
||||
}));
|
||||
}, [customConfigurations, logFilePaths, namespace, serviceName, setState]);
|
||||
|
||||
function addLogFilePath() {
|
||||
setLogFilePaths((prev) => [...prev, '']);
|
||||
}
|
||||
|
||||
function removeLogFilePath(index: number) {
|
||||
setLogFilePaths((prev) => prev.filter((_, i) => i !== index));
|
||||
}
|
||||
|
||||
function onLogFilePathChanges(index: number, event: React.FormEvent<HTMLInputElement>) {
|
||||
const filepath = event.currentTarget?.value;
|
||||
setLogFilePaths((prev) => prev.map((path, i) => (i === index ? filepath : path)));
|
||||
|
||||
if (index === 0) {
|
||||
if (updateCreateFields) {
|
||||
updateCreateFields({
|
||||
integrationName: getFilename(filepath).toLowerCase(),
|
||||
datasets: [
|
||||
{
|
||||
name: getFilename(filepath).toLowerCase(),
|
||||
type: 'logs' as const,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<StepModal
|
||||
title={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogsContent.stepModal.collectCustomLogsLabel',
|
||||
{ defaultMessage: 'Collect custom logs' }
|
||||
)}
|
||||
panelFooter={[
|
||||
<ConnectedCustomIntegrationsButton
|
||||
isDisabled={logFilePathNotConfigured || !namespace}
|
||||
onClick={onContinue}
|
||||
testSubj={customIntegrationsTestSubjects.button}
|
||||
/>,
|
||||
]}
|
||||
>
|
||||
<EuiForm fullWidth>
|
||||
<EuiText color="subdued">
|
||||
<p>
|
||||
{i18n.translate('xpack.observability_onboarding.configureLogs.description', {
|
||||
defaultMessage: 'Configure inputs',
|
||||
})}
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer size="l" />
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.observability_onboarding.configureLogs.logFile.path', {
|
||||
defaultMessage: 'Log file path',
|
||||
})}
|
||||
helpText={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogs.logFile.helperText',
|
||||
{
|
||||
defaultMessage: 'You can use a file path or pattern.',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<>
|
||||
{logFilePaths.map((filepath, index) => (
|
||||
<div key={index} data-test-subj={`obltOnboardingLogFilePath-${index}`}>
|
||||
{index > 0 && <EuiSpacer size="s" />}
|
||||
<EuiFlexGroup alignItems="center" gutterSize="xs">
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
data-test-subj="observabilityOnboardingConfigureLogsFieldText"
|
||||
placeholder={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogs.logFile.placeholder',
|
||||
{
|
||||
defaultMessage: 'Example: /var/log/application.*',
|
||||
}
|
||||
)}
|
||||
value={filepath}
|
||||
onChange={(ev) => onLogFilePathChanges(index, ev)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
{index > 0 && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
iconType="trash"
|
||||
aria-label={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogsContent.euiButtonIcon.deleteLabel',
|
||||
{ defaultMessage: 'Delete' }
|
||||
)}
|
||||
onClick={() => removeLogFilePath(index)}
|
||||
data-test-subj={`obltOnboardingLogFilePathDelete-${index}`}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
</EuiFormRow>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFlexGroup alignItems="flexStart" direction="column" gutterSize="xs">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
iconType="plusInCircle"
|
||||
onClick={addLogFilePath}
|
||||
data-test-subj="obltOnboardingCustomLogsAddFilePath"
|
||||
>
|
||||
{i18n.translate('xpack.observability_onboarding.configureLogs.logFile.addRow', {
|
||||
defaultMessage: 'Add row',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="s" />
|
||||
<OptionalFormRow
|
||||
label={
|
||||
<EuiFlexGroup alignItems="center" gutterSize="xs" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
{i18n.translate('xpack.observability_onboarding.configureLogs.serviceName', {
|
||||
defaultMessage: 'Service name',
|
||||
})}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIconTip
|
||||
content={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogs.serviceName.tooltip',
|
||||
{
|
||||
defaultMessage:
|
||||
'Provide a service name to allow for distributed services running on multiple hosts to correlate the related instances.',
|
||||
}
|
||||
)}
|
||||
position="right"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="xpack.observability_onboarding.configureLogs.serviceName.helper"
|
||||
defaultMessage="Name the service your data is collected from."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
placeholder={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogs.serviceName.placeholder',
|
||||
{
|
||||
defaultMessage: 'Give your service a name',
|
||||
}
|
||||
)}
|
||||
value={serviceName}
|
||||
onChange={(event) => setServiceName(event.target.value)}
|
||||
data-test-subj="obltOnboardingCustomLogsServiceName"
|
||||
/>
|
||||
</OptionalFormRow>
|
||||
<EuiHorizontalRule margin="m" />
|
||||
<EuiAccordion
|
||||
id="advancedSettingsAccordion"
|
||||
css={{
|
||||
'.euiAccordion__buttonContent': {
|
||||
color: euiTheme.colors.textPrimary,
|
||||
fontSize: xsFontSize,
|
||||
},
|
||||
'.euiAccordion__arrow svg': {
|
||||
stroke: euiTheme.colors.primary,
|
||||
width: euiTheme.size.m,
|
||||
height: euiTheme.size.m,
|
||||
},
|
||||
}}
|
||||
buttonContent={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogs.advancedSettings',
|
||||
{
|
||||
defaultMessage: 'Advanced settings',
|
||||
}
|
||||
)}
|
||||
data-test-subj="obltOnboardingCustomLogsAdvancedSettings"
|
||||
>
|
||||
<EuiSpacer size="l" />
|
||||
<EuiFormRow
|
||||
label={
|
||||
<EuiFlexGroup alignItems="center" gutterSize="xs" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
{i18n.translate('xpack.observability_onboarding.configureLogs.namespace', {
|
||||
defaultMessage: 'Namespace',
|
||||
})}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIconTip
|
||||
content={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogs.namespace.tooltip',
|
||||
{
|
||||
defaultMessage:
|
||||
'Provide a namespace to customize the grouping of your logs. Defaults to the default namespace.',
|
||||
}
|
||||
)}
|
||||
position="right"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="xpack.observability_onboarding.configureLogs.namespace.helper"
|
||||
defaultMessage="This setting changes the name of the integration's data stream. {learnMoreLink}"
|
||||
values={{
|
||||
learnMoreLink: (
|
||||
<EuiLink
|
||||
data-test-subj="observabilityOnboardingConfigureLogsLearnMoreLink"
|
||||
external
|
||||
target="_blank"
|
||||
href={
|
||||
'https://www.elastic.co/guide/en/fleet/current/data-streams.html#data-streams-naming-scheme'
|
||||
}
|
||||
>
|
||||
{i18n.translate('xpack.observability_onboarding.configureLogs.learnMore', {
|
||||
defaultMessage: 'Learn more',
|
||||
})}
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
placeholder={i18n.translate(
|
||||
'xpack.observability_onboarding.configureLogs.namespace.placeholder',
|
||||
{
|
||||
defaultMessage: 'Namespace',
|
||||
}
|
||||
)}
|
||||
value={namespace}
|
||||
onChange={(event) => setNamespace(event.target.value)}
|
||||
data-test-subj="obltOnboardingCustomLogsNamespace"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiSpacer size="l" />
|
||||
<OptionalFormRow
|
||||
label={i18n.translate('xpack.observability_onboarding.configureLogs.customConfig', {
|
||||
defaultMessage: 'Custom configurations',
|
||||
})}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="xpack.observability_onboarding.configureLogs.customConfig.helper"
|
||||
defaultMessage="Add YAML configuration options to your agent configuration. Be careful using this feature as it can break your configuration file. {learnMoreLink}"
|
||||
values={{
|
||||
learnMoreLink: (
|
||||
<EuiLink
|
||||
data-test-subj="observabilityOnboardingConfigureLogsLearnMoreLink"
|
||||
external
|
||||
target="_blank"
|
||||
href={
|
||||
'https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html'
|
||||
}
|
||||
>
|
||||
{i18n.translate('xpack.observability_onboarding.configureLogs.learnMore', {
|
||||
defaultMessage: 'Learn more',
|
||||
})}
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiTextArea
|
||||
value={customConfigurations}
|
||||
onChange={(event) => setCustomConfigurations(event.target.value)}
|
||||
data-test-subj="obltOnboardingCustomLogsCustomConfig"
|
||||
/>
|
||||
</OptionalFormRow>
|
||||
</EuiAccordion>
|
||||
<EuiSpacer size="l" />
|
||||
<ConnectedCustomIntegrationsForm testSubjects={customIntegrationsTestSubjects} />
|
||||
</EuiForm>
|
||||
</StepModal>
|
||||
);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* 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 { getFilename } from './get_filename';
|
||||
|
||||
describe('Observability onboarding - get_filename', () => {
|
||||
it.each([
|
||||
['test', '/logs-onboarding/test.log'],
|
||||
['test', '/logs-onboarding/test.log'],
|
||||
['test', 'test.log'],
|
||||
['test', '/logs-onboarding/long-path/test.log'],
|
||||
['test', '/logs-onboarding/test.20240223.log'],
|
||||
['test', 'test'],
|
||||
['', ''],
|
||||
['test', '\\logs-onboarding\\test.log'],
|
||||
['test', "/logs-on'boarding/test.log"],
|
||||
['te_st', "/logs-on'boarding/te'st.log"],
|
||||
['test_123', '/logs-onboarding/test 123.log'],
|
||||
['t_e_s_t_1_2_3_', '/logs-onboarding/t-e%s*t#1@2!3$.log'],
|
||||
])('should return "%s" for filename "%s"', (expectedFilename: string, filePath: string) => {
|
||||
expect(getFilename(filePath)).toBe(expectedFilename);
|
||||
});
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* 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 const getFilename = (path?: string) => {
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const filenameWithExt = path.replace(/^.*[\\\/](?!\d*$)/g, '');
|
||||
const filenameParts = filenameWithExt.split('.');
|
||||
|
||||
return replaceSpecialChars(filenameParts[0]);
|
||||
};
|
||||
|
||||
export const replaceSpecialChars = (filename: string) => filename.replaceAll(/[^a-zA-Z0-9_]/g, '_');
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { EuiPanel } from '@elastic/eui';
|
||||
import { CustomIntegrationOptions } from '@kbn/custom-integrations';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Route } from '@kbn/shared-ux-router';
|
||||
import { createWizardContext, Step } from '../../../context/create_wizard_context';
|
||||
import { ConfigureLogs } from './configure_logs';
|
||||
import { Inspect } from './inspect';
|
||||
import { InstallElasticAgent } from './install_elastic_agent';
|
||||
import { FeedbackButtons } from '../shared/feedback_buttons';
|
||||
|
||||
interface WizardState {
|
||||
integrationName?: string;
|
||||
lastCreatedIntegrationOptions?: CustomIntegrationOptions;
|
||||
datasetName?: string;
|
||||
serviceName: string;
|
||||
logFilePaths: string[];
|
||||
namespace: string;
|
||||
customConfigurations: string;
|
||||
logsType?: 'system' | 'sys' | 'http-endpoint' | 'opentelemetry' | 'log-file' | 'service';
|
||||
uploadType?: 'log-file' | 'api-key';
|
||||
elasticAgentPlatform: 'linux-tar' | 'macos' | 'windows' | 'deb' | 'rpm';
|
||||
autoDownloadConfig: boolean;
|
||||
apiKeyEncoded: string;
|
||||
onboardingId: string;
|
||||
}
|
||||
|
||||
const initialState: WizardState = {
|
||||
integrationName: undefined,
|
||||
datasetName: undefined,
|
||||
serviceName: '',
|
||||
logFilePaths: [''],
|
||||
namespace: 'default',
|
||||
customConfigurations: '',
|
||||
elasticAgentPlatform: 'linux-tar',
|
||||
autoDownloadConfig: false,
|
||||
apiKeyEncoded: '',
|
||||
onboardingId: '',
|
||||
};
|
||||
|
||||
export type CustomLogsSteps = 'configureLogs' | 'installElasticAgent' | 'inspect';
|
||||
|
||||
const steps: Record<CustomLogsSteps, Step> = {
|
||||
configureLogs: { component: ConfigureLogs },
|
||||
installElasticAgent: {
|
||||
component: InstallElasticAgent,
|
||||
title: i18n.translate('xpack.observability_onboarding.customLogs.installShipper.title', {
|
||||
defaultMessage: 'Install shipper to collect logs',
|
||||
}),
|
||||
},
|
||||
inspect: { component: Inspect },
|
||||
};
|
||||
|
||||
const {
|
||||
Provider,
|
||||
useWizard,
|
||||
routes: customLogsRoutes,
|
||||
} = createWizardContext({
|
||||
initialState,
|
||||
initialStep: 'configureLogs',
|
||||
steps,
|
||||
basePath: '/customLogs',
|
||||
});
|
||||
|
||||
export { Provider, useWizard, customLogsRoutes };
|
||||
|
||||
export const CustomLogsPanel: React.FC = () => {
|
||||
return (
|
||||
<Provider>
|
||||
<EuiPanel hasBorder>
|
||||
{Object.keys(customLogsRoutes).map((key) => {
|
||||
const path = key as keyof typeof customLogsRoutes;
|
||||
const { handler, exact } = customLogsRoutes[path];
|
||||
return <Route key={path} path={path} exact={exact} component={handler} />;
|
||||
})}
|
||||
<FeedbackButtons flow="custom-logs" />
|
||||
</EuiPanel>
|
||||
</Provider>
|
||||
);
|
||||
};
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiTitle, EuiSpacer } from '@elastic/eui';
|
||||
import { StepModal } from '../shared/step_panel';
|
||||
import { useWizard } from '.';
|
||||
import { BackButton } from '../../shared/back_button';
|
||||
|
||||
export function Inspect() {
|
||||
const { getState, getPath, getUsage } = useWizard();
|
||||
return (
|
||||
<StepModal
|
||||
title={i18n.translate('xpack.observability_onboarding.inspect.stepPanel.inspectWizardLabel', {
|
||||
defaultMessage: 'Inspect wizard',
|
||||
})}
|
||||
panelFooter={[<BackButton />]}
|
||||
>
|
||||
<EuiTitle size="s">
|
||||
<h3>
|
||||
{i18n.translate('xpack.observability_onboarding.inspect.h3.stateLabel', {
|
||||
defaultMessage: 'State',
|
||||
})}
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
<pre>{JSON.stringify(getState(), null, 4)}</pre>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiTitle size="s">
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="xpack.observability_onboarding.inspect.h3.pathLabel"
|
||||
defaultMessage="Path"
|
||||
/>
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
<pre>{JSON.stringify(getPath(), null, 4)}</pre>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiTitle size="s">
|
||||
<h3>
|
||||
{i18n.translate('xpack.observability_onboarding.inspect.h3.usageLabel', {
|
||||
defaultMessage: 'Usage',
|
||||
})}
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
<pre>{JSON.stringify(getUsage(), null, 4)}</pre>
|
||||
</StepModal>
|
||||
);
|
||||
}
|
|
@ -1,376 +0,0 @@
|
|||
/*
|
||||
* 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 { EuiButton, EuiCallOut, EuiHorizontalRule, EuiSpacer, EuiText } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { default as React, useCallback, useEffect, useState } from 'react';
|
||||
import { type LogsLocatorParams, LOGS_LOCATOR_ID } from '@kbn/logs-shared-plugin/common';
|
||||
import { OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT } from '../../../../common/telemetry_events';
|
||||
import { ObservabilityOnboardingPluginSetupDeps } from '../../../plugin';
|
||||
import { useWizard } from '.';
|
||||
import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher';
|
||||
import {
|
||||
ElasticAgentPlatform,
|
||||
getElasticAgentSetupCommand,
|
||||
} from '../shared/get_elastic_agent_setup_command';
|
||||
import {
|
||||
InstallElasticAgentSteps,
|
||||
ProgressStepId,
|
||||
EuiStepStatus,
|
||||
} from '../shared/install_elastic_agent_steps';
|
||||
import { StepModal } from '../shared/step_panel';
|
||||
import { ApiKeyBanner } from './api_key_banner';
|
||||
import { WindowsInstallStep } from '../shared/windows_install_step';
|
||||
import { TroubleshootingLink } from '../shared/troubleshooting_link';
|
||||
|
||||
const defaultDatasetName = '';
|
||||
|
||||
export function InstallElasticAgent() {
|
||||
const {
|
||||
services: { share, analytics },
|
||||
} = useKibana<ObservabilityOnboardingPluginSetupDeps>();
|
||||
const [dataReceivedTelemetrySent, setDataReceivedTelemetrySent] = useState(false);
|
||||
|
||||
const logsLocator = share.url.locators.get<LogsLocatorParams>(LOGS_LOCATOR_ID);
|
||||
|
||||
const { getState, setState } = useWizard();
|
||||
const wizardState = getState();
|
||||
const { integrationName: integration, datasetName: dataset, autoDownloadConfig } = wizardState;
|
||||
|
||||
const [elasticAgentPlatform, setElasticAgentPlatform] =
|
||||
useState<ElasticAgentPlatform>('linux-tar');
|
||||
|
||||
const enforcedDatasetName =
|
||||
(integration === dataset ? dataset : `${integration}.${dataset}`) ?? defaultDatasetName;
|
||||
|
||||
async function onContinue() {
|
||||
await logsLocator!.navigate({
|
||||
dataViewSpec: {
|
||||
title: `logs-${enforcedDatasetName}-*`,
|
||||
timeFieldName: '@timestamp',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function onAutoDownloadConfig() {
|
||||
setState((state) => ({
|
||||
...state,
|
||||
autoDownloadConfig: !state.autoDownloadConfig,
|
||||
}));
|
||||
}
|
||||
|
||||
const { data: monitoringRole, status: monitoringRoleStatus } = useFetcher((callApi) => {
|
||||
if (!hasAlreadySavedFlow(getState())) {
|
||||
return callApi('GET /internal/observability_onboarding/logs/setup/privileges');
|
||||
}
|
||||
// FIXME: Dario could not find a reasonable fix for getState()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const { data: setup } = useFetcher((callApi) => {
|
||||
return callApi('GET /internal/observability_onboarding/logs/setup/environment');
|
||||
}, []);
|
||||
|
||||
const {
|
||||
data: installShipperSetup,
|
||||
status: installShipperSetupStatus,
|
||||
error,
|
||||
} = useFetcher(
|
||||
(callApi) => {
|
||||
const { datasetName, serviceName, namespace, customConfigurations, logFilePaths } =
|
||||
getState();
|
||||
if (!hasAlreadySavedFlow(getState()) && monitoringRole?.hasPrivileges && datasetName) {
|
||||
return callApi('POST /internal/observability_onboarding/logs/flow', {
|
||||
params: {
|
||||
body: {
|
||||
name: datasetName,
|
||||
type: 'logFiles',
|
||||
state: {
|
||||
datasetName,
|
||||
serviceName,
|
||||
namespace,
|
||||
customConfigurations,
|
||||
logFilePaths,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
// FIXME: Dario could not find a reasonable fix for getState()
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[monitoringRole?.hasPrivileges]
|
||||
);
|
||||
|
||||
const { status: saveOnboardingStateDataStatus } = useFetcher((callApi) => {
|
||||
const {
|
||||
onboardingId,
|
||||
datasetName,
|
||||
serviceName,
|
||||
namespace,
|
||||
customConfigurations,
|
||||
logFilePaths,
|
||||
} = getState();
|
||||
if (onboardingId) {
|
||||
return callApi('PUT /internal/observability_onboarding/flow/{onboardingId}', {
|
||||
params: {
|
||||
path: { onboardingId },
|
||||
body: {
|
||||
state: {
|
||||
datasetName,
|
||||
serviceName,
|
||||
namespace,
|
||||
customConfigurations,
|
||||
logFilePaths,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
// FIXME: Dario could not find a reasonable fix for getState()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const { apiKeyEncoded, onboardingId } = installShipperSetup ?? getState();
|
||||
|
||||
const succesfullySavedOnboardingState = saveOnboardingStateDataStatus === FETCH_STATUS.SUCCESS;
|
||||
|
||||
const { data: yamlConfig = '', status: yamlConfigStatus } = useFetcher(
|
||||
(callApi) => {
|
||||
if (apiKeyEncoded && onboardingId) {
|
||||
return callApi('GET /internal/observability_onboarding/elastic_agent/config', {
|
||||
headers: { authorization: `ApiKey ${apiKeyEncoded}` },
|
||||
params: { query: { onboardingId } },
|
||||
});
|
||||
}
|
||||
},
|
||||
// FIXME: Dario could not find a reasonable fix for succesfullySavedOnboardingState
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[apiKeyEncoded, onboardingId, succesfullySavedOnboardingState]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setState((state) => ({ ...state, onboardingId, apiKeyEncoded }));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [onboardingId, apiKeyEncoded]);
|
||||
|
||||
const {
|
||||
data: progressData,
|
||||
status: progressStatus,
|
||||
refetch: refetchProgress,
|
||||
} = useFetcher(
|
||||
(callApi) => {
|
||||
if (onboardingId) {
|
||||
return callApi('GET /internal/observability_onboarding/flow/{onboardingId}/progress', {
|
||||
params: { path: { onboardingId } },
|
||||
});
|
||||
}
|
||||
},
|
||||
[onboardingId]
|
||||
);
|
||||
|
||||
const progressSucceded = progressStatus === FETCH_STATUS.SUCCESS;
|
||||
|
||||
useEffect(() => {
|
||||
if (progressSucceded) {
|
||||
setTimeout(() => {
|
||||
refetchProgress();
|
||||
}, 2000);
|
||||
}
|
||||
}, [progressSucceded, refetchProgress]);
|
||||
|
||||
const getCheckLogsStep = useCallback(() => {
|
||||
const progress = progressData?.progress;
|
||||
if (progress) {
|
||||
const stepStatus = progress?.['logs-ingest']?.status as EuiStepStatus;
|
||||
const title =
|
||||
stepStatus === 'loading'
|
||||
? CHECK_LOGS_LABELS.loading
|
||||
: stepStatus === 'complete'
|
||||
? CHECK_LOGS_LABELS.completed
|
||||
: CHECK_LOGS_LABELS.incomplete;
|
||||
return {
|
||||
title,
|
||||
status: stepStatus,
|
||||
'data-test-subj': 'obltOnboardingCheckLogsStep',
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: CHECK_LOGS_LABELS.incomplete,
|
||||
status: 'incomplete' as const,
|
||||
};
|
||||
}, [progressData?.progress]);
|
||||
|
||||
const isInstallStarted = progressData?.progress['ea-download'] !== undefined;
|
||||
const isInstallCompleted = progressData?.progress?.['ea-status']?.status === 'complete';
|
||||
const autoDownloadConfigStatus = (progressData?.progress?.['ea-config']?.status ??
|
||||
'incomplete') as EuiStepStatus;
|
||||
const isIngestCompleted = progressData?.progress?.['logs-ingest']?.status === 'complete';
|
||||
|
||||
useEffect(() => {
|
||||
if (isIngestCompleted && !dataReceivedTelemetrySent) {
|
||||
setDataReceivedTelemetrySent(true);
|
||||
analytics?.reportEvent(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.eventType, {
|
||||
flow_type: 'logFiles',
|
||||
flow_id: onboardingId,
|
||||
step: 'logs-ingest',
|
||||
step_status: 'complete',
|
||||
});
|
||||
}
|
||||
}, [analytics, dataReceivedTelemetrySent, isIngestCompleted, onboardingId]);
|
||||
|
||||
return (
|
||||
<StepModal
|
||||
panelFooter={[
|
||||
<EuiButton
|
||||
data-test-subj="obltOnboardingExploreLogs"
|
||||
color="primary"
|
||||
fill
|
||||
iconType="magnifyWithPlus"
|
||||
onClick={onContinue}
|
||||
>
|
||||
{i18n.translate('xpack.observability_onboarding.steps.exploreLogs', {
|
||||
defaultMessage: 'Explore logs',
|
||||
})}
|
||||
</EuiButton>,
|
||||
]}
|
||||
>
|
||||
<EuiText color="subdued">
|
||||
<p>
|
||||
{i18n.translate('xpack.observability_onboarding.installElasticAgent.description', {
|
||||
defaultMessage:
|
||||
'To collect the data from your system and stream it to Elastic, you first need to install a shipping tool on the machine generating the logs. In this case, the shipping tool is an agent developed by Elastic.',
|
||||
})}
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer size="m" />
|
||||
{integration && (
|
||||
<>
|
||||
<EuiCallOut
|
||||
title={i18n.translate(
|
||||
'xpack.observability_onboarding.installElasticAgent.integrationSuccessCallout.title',
|
||||
{
|
||||
defaultMessage: '{integrationName} integration installed.',
|
||||
values: {
|
||||
integrationName: integration,
|
||||
},
|
||||
}
|
||||
)}
|
||||
color="success"
|
||||
iconType="check"
|
||||
data-test-subj="obltOnboardingCustomIntegrationInstalled"
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
)}
|
||||
{apiKeyEncoded && onboardingId ? (
|
||||
<ApiKeyBanner
|
||||
payload={{ apiKeyEncoded, onboardingId }}
|
||||
hasPrivileges
|
||||
status={FETCH_STATUS.SUCCESS}
|
||||
/>
|
||||
) : (
|
||||
monitoringRoleStatus !== FETCH_STATUS.NOT_INITIATED &&
|
||||
monitoringRoleStatus !== FETCH_STATUS.LOADING && (
|
||||
<ApiKeyBanner
|
||||
payload={installShipperSetup}
|
||||
hasPrivileges={monitoringRole?.hasPrivileges}
|
||||
status={installShipperSetupStatus}
|
||||
error={error}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
<EuiSpacer size="m" />
|
||||
<InstallElasticAgentSteps
|
||||
installAgentPlatformOptions={[
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.linux',
|
||||
{ defaultMessage: 'Linux' }
|
||||
),
|
||||
id: 'linux-tar',
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.macOS',
|
||||
{ defaultMessage: 'MacOS' }
|
||||
),
|
||||
id: 'macos',
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.windows',
|
||||
{ defaultMessage: 'Windows' }
|
||||
),
|
||||
id: 'windows',
|
||||
disableSteps: true,
|
||||
children: (
|
||||
<WindowsInstallStep docsLink="https://www.elastic.co/guide/en/observability/current/logs-stream.html" />
|
||||
),
|
||||
},
|
||||
]}
|
||||
onSelectPlatform={(id) => setElasticAgentPlatform(id)}
|
||||
selectedPlatform={elasticAgentPlatform}
|
||||
installAgentCommand={getElasticAgentSetupCommand({
|
||||
elasticAgentPlatform,
|
||||
apiKeyEncoded,
|
||||
apiEndpoint: setup?.apiEndpoint,
|
||||
scriptDownloadUrl: setup?.scriptDownloadUrl,
|
||||
elasticAgentVersion: setup?.elasticAgentVersionInfo.agentVersion,
|
||||
autoDownloadConfig,
|
||||
onboardingId,
|
||||
})}
|
||||
autoDownloadConfig={autoDownloadConfig}
|
||||
onToggleAutoDownloadConfig={onAutoDownloadConfig}
|
||||
installAgentStatus={
|
||||
installShipperSetupStatus === FETCH_STATUS.LOADING
|
||||
? 'loading'
|
||||
: isInstallCompleted
|
||||
? 'complete'
|
||||
: 'current'
|
||||
}
|
||||
showInstallProgressSteps={isInstallStarted}
|
||||
installProgressSteps={
|
||||
(progressData?.progress ?? {}) as Partial<
|
||||
Record<ProgressStepId, { status: EuiStepStatus; message?: string }>
|
||||
>
|
||||
}
|
||||
configureAgentStatus={
|
||||
yamlConfigStatus === FETCH_STATUS.LOADING ? 'loading' : autoDownloadConfigStatus
|
||||
}
|
||||
configureAgentYaml={yamlConfig}
|
||||
appendedSteps={[getCheckLogsStep()]}
|
||||
/>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
<TroubleshootingLink />
|
||||
</StepModal>
|
||||
);
|
||||
}
|
||||
|
||||
type WizardState = ReturnType<ReturnType<typeof useWizard>['getState']>;
|
||||
function hasAlreadySavedFlow({ apiKeyEncoded, onboardingId }: WizardState) {
|
||||
return Boolean(apiKeyEncoded && onboardingId);
|
||||
}
|
||||
|
||||
const CHECK_LOGS_LABELS = {
|
||||
incomplete: i18n.translate(
|
||||
'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.incompleteTitle',
|
||||
{ defaultMessage: 'Ship logs to Elastic Observability' }
|
||||
),
|
||||
loading: i18n.translate(
|
||||
'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.loadingTitle',
|
||||
{ defaultMessage: 'Waiting for logs to be shipped...' }
|
||||
),
|
||||
completed: i18n.translate(
|
||||
'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.completedTitle',
|
||||
{ defaultMessage: 'Logs are being shipped!' }
|
||||
),
|
||||
};
|
|
@ -59,34 +59,32 @@ export const OtelLogsPanel: React.FC = () => {
|
|||
} = useKibana<ObservabilityOnboardingAppServices>();
|
||||
|
||||
const {
|
||||
data: apiKeyData,
|
||||
data: setupData,
|
||||
error,
|
||||
refetch,
|
||||
} = useFetcher(
|
||||
(callApi) => {
|
||||
return callApi('POST /internal/observability_onboarding/otel/api_key', {});
|
||||
return callApi('POST /internal/observability_onboarding/otel_host/setup');
|
||||
},
|
||||
[],
|
||||
{ showToastOnError: false }
|
||||
);
|
||||
|
||||
const { data: setup } = useFetcher((callApi) => {
|
||||
return callApi('GET /internal/observability_onboarding/logs/setup/environment');
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (apiKeyData && setup) {
|
||||
if (setupData) {
|
||||
onPageReady({
|
||||
meta: {
|
||||
description: `[ttfmp_onboarding] Requests to get the environment and to generate API key succeeded and the flow's UI has rendered`,
|
||||
description: `[ttfmp_onboarding] Requests to setup the flow succeeded and the flow's UI has rendered`,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [apiKeyData, onPageReady, setup]);
|
||||
}, [onPageReady, setupData]);
|
||||
|
||||
const ingestEndpointUrl = isServerless ? setup?.managedOtlpServiceUrl : setup?.elasticsearchUrl;
|
||||
const ingestEndpointUrl = isServerless
|
||||
? setupData?.managedOtlpServiceUrl
|
||||
: setupData?.elasticsearchUrl;
|
||||
const AGENT_CDN_BASE_URL = 'artifacts.elastic.co/downloads/beats/elastic-agent';
|
||||
const agentVersion = setup?.elasticAgentVersionInfo.agentVersion ?? '';
|
||||
const agentVersion = setupData?.elasticAgentVersionInfo.agentVersion ?? '';
|
||||
const urlEncodedAgentVersion = encodeURIComponent(agentVersion);
|
||||
|
||||
const logsLocator = share.url.locators.get<LogsLocatorParams>(LOGS_LOCATOR_ID);
|
||||
|
@ -117,7 +115,7 @@ export const OtelLogsPanel: React.FC = () => {
|
|||
|
||||
curl --output elastic-distro-${agentVersion}-linux-$arch.tar.gz --url https://${AGENT_CDN_BASE_URL}/elastic-agent-${urlEncodedAgentVersion}-linux-$arch.tar.gz --proto '=https' --tlsv1.2 -fL && mkdir -p elastic-distro-${agentVersion}-linux-$arch && tar -xvf elastic-distro-${agentVersion}-linux-$arch.tar.gz -C "elastic-distro-${agentVersion}-linux-$arch" --strip-components=1 && cd elastic-distro-${agentVersion}-linux-$arch
|
||||
|
||||
rm ./otel.yml && cp ${sampleConfigurationPath} ./otel.yml && mkdir -p ./data/otelcol && sed -i 's#\\\${env:STORAGE_DIR}#'"$PWD"/data/otelcol'#g' ./otel.yml && sed -i 's#\\\${env:${elasticEndpointVarName}}#${ingestEndpointUrl}#g' ./otel.yml && sed -i 's/\\\${env:ELASTIC_API_KEY}/${apiKeyData?.apiKeyEncoded}/g' ./otel.yml`,
|
||||
rm ./otel.yml && cp ${sampleConfigurationPath} ./otel.yml && mkdir -p ./data/otelcol && sed -i 's#\\\${env:STORAGE_DIR}#'"$PWD"/data/otelcol'#g' ./otel.yml && sed -i 's#\\\${env:${elasticEndpointVarName}}#${ingestEndpointUrl}#g' ./otel.yml && sed -i 's/\\\${env:ELASTIC_API_KEY}/${setupData?.apiKeyEncoded}/g' ./otel.yml`,
|
||||
start: 'sudo ./otelcol --config otel.yml',
|
||||
type: 'copy',
|
||||
},
|
||||
|
@ -129,7 +127,7 @@ rm ./otel.yml && cp ${sampleConfigurationPath} ./otel.yml && mkdir -p ./data/ote
|
|||
|
||||
curl --output elastic-distro-${agentVersion}-darwin-$arch.tar.gz --url https://${AGENT_CDN_BASE_URL}/elastic-agent-${urlEncodedAgentVersion}-darwin-$arch.tar.gz --proto '=https' --tlsv1.2 -fL && mkdir -p "elastic-distro-${agentVersion}-darwin-$arch" && tar -xvf elastic-distro-${agentVersion}-darwin-$arch.tar.gz -C "elastic-distro-${agentVersion}-darwin-$arch" --strip-components=1 && cd elastic-distro-${agentVersion}-darwin-$arch
|
||||
|
||||
rm ./otel.yml && cp ${sampleConfigurationPath} ./otel.yml && mkdir -p ./data/otelcol && sed -i '' 's#\\\${env:STORAGE_DIR}#'"$PWD"/data/otelcol'#g' ./otel.yml && sed -i '' 's#\\\${env:${elasticEndpointVarName}}#${ingestEndpointUrl}#g' ./otel.yml && sed -i '' 's/\\\${env:ELASTIC_API_KEY}/${apiKeyData?.apiKeyEncoded}/g' ./otel.yml`,
|
||||
rm ./otel.yml && cp ${sampleConfigurationPath} ./otel.yml && mkdir -p ./data/otelcol && sed -i '' 's#\\\${env:STORAGE_DIR}#'"$PWD"/data/otelcol'#g' ./otel.yml && sed -i '' 's#\\\${env:${elasticEndpointVarName}}#${ingestEndpointUrl}#g' ./otel.yml && sed -i '' 's/\\\${env:ELASTIC_API_KEY}/${setupData?.apiKeyEncoded}/g' ./otel.yml`,
|
||||
start: './otelcol --config otel.yml',
|
||||
type: 'copy',
|
||||
},
|
||||
|
@ -172,9 +170,9 @@ rm ./otel.yml && cp ${sampleConfigurationPath} ./otel.yml && mkdir -p ./data/ote
|
|||
}}
|
||||
/>
|
||||
|
||||
{(!setup || !apiKeyData) && <EuiSkeletonText lines={6} />}
|
||||
{!setupData && <EuiSkeletonText lines={6} />}
|
||||
|
||||
{setup && apiKeyData && (
|
||||
{setupData && (
|
||||
<>
|
||||
<EuiText>
|
||||
<p>{selectedContent.firstStepTitle}</p>
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -u
|
||||
|
||||
fail() {
|
||||
printf "%s\n" "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# require bash
|
||||
if [ -z "${BASH_VERSION:-}" ]; then
|
||||
fail "bash required"
|
||||
fi
|
||||
|
||||
if [ $# -lt 4 ]; then
|
||||
fail "usage: $0 api_key api_endpoint agent_version onboarding_id [autoDownloadConfig=1]"
|
||||
fi
|
||||
|
||||
API_KEY_ENCODED=$1
|
||||
API_ENDPOINT=$2
|
||||
ELASTIC_AGENT_VERSION=$3
|
||||
ONBOARDING_ID=$4
|
||||
AUTO_DOWNLOAD_CONFIG=${5:-}
|
||||
|
||||
# require curl
|
||||
[ $(builtin type -P curl) ] || fail "curl required"
|
||||
|
||||
# check OS
|
||||
OS="$(uname)"
|
||||
ARCH="$(uname -m)"
|
||||
os=linux
|
||||
arch=x86_64
|
||||
cfg=/opt/Elastic/Agent/elastic-agent.yml
|
||||
if [ "${OS}" == "Linux" ]; then
|
||||
if [ "${ARCH}" == "aarch64" ]; then
|
||||
arch=arm64
|
||||
fi
|
||||
elif [ "${OS}" == "Darwin" ]; then
|
||||
os=darwin
|
||||
if [ "${ARCH}" == "arm64" ]; then
|
||||
arch=aarch64
|
||||
fi
|
||||
cfg=/Library/Elastic/Agent/elastic-agent.yml
|
||||
else
|
||||
fail "this script is only supported on linux and macOS"
|
||||
fi
|
||||
|
||||
artifact=elastic-agent-${ELASTIC_AGENT_VERSION}-${os}-${arch}
|
||||
|
||||
# https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.8.2-darwin-x86_64.tar.gz
|
||||
# https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.8.2-darwin-aarch64.tar.gz
|
||||
# https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.8.2-linux-x86_64.tar.gz
|
||||
# https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.8.2-linux-arm64.tar.gz
|
||||
|
||||
updateStepProgress() {
|
||||
local STEPNAME="$1"
|
||||
local STATUS="$2" # "incomplete" | "complete" | "disabled" | "loading" | "warning" | "danger" | "current"
|
||||
local MESSAGE=${3:-}
|
||||
local PAYLOAD=${4:-}
|
||||
local data=""
|
||||
if [ -z "$PAYLOAD" ]; then
|
||||
data="{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\"}"
|
||||
else
|
||||
data="{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\", \"payload\":${PAYLOAD}}"
|
||||
fi
|
||||
curl --request POST \
|
||||
--url "${API_ENDPOINT}/flow/${ONBOARDING_ID}/step/${STEPNAME}" \
|
||||
--header "Authorization: ApiKey ${API_KEY_ENCODED}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "kbn-xsrf: true" \
|
||||
--header "x-elastic-internal-origin: Kibana" \
|
||||
--data "$data" \
|
||||
--output /dev/null \
|
||||
--no-progress-meter
|
||||
}
|
||||
|
||||
ELASTIC_AGENT_DOWNLOAD_URL="https://artifacts.elastic.co/downloads/beats/elastic-agent/${artifact}.tar.gz"
|
||||
echo "Downloading Elastic Agent archive from ${ELASTIC_AGENT_DOWNLOAD_URL}"
|
||||
updateStepProgress "ea-download" "loading"
|
||||
curl -L -O $ELASTIC_AGENT_DOWNLOAD_URL --fail
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo "Downloaded Elastic Agent"
|
||||
updateStepProgress "ea-download" "complete"
|
||||
else
|
||||
updateStepProgress "ea-download" "danger" "Failed to download Elastic Agent, see script output for error."
|
||||
fail "Failed to download Elastic Agent"
|
||||
fi
|
||||
|
||||
echo "Extracting Elastic Agent"
|
||||
updateStepProgress "ea-extract" "loading"
|
||||
tar -xzf ${artifact}.tar.gz
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo "Elastic Agent extracted"
|
||||
updateStepProgress "ea-extract" "complete"
|
||||
else
|
||||
updateStepProgress "ea-extract" "danger" "Failed to extract Elastic Agent, see script output for error."
|
||||
fail "Failed to extract Elastic Agent"
|
||||
fi
|
||||
|
||||
echo "Installing Elastic Agent"
|
||||
updateStepProgress "ea-install" "loading"
|
||||
cd ${artifact}
|
||||
./elastic-agent install -f
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo "Elastic Agent installed"
|
||||
updateStepProgress "ea-install" "complete"
|
||||
else
|
||||
updateStepProgress "ea-install" "danger" "Failed to install Elastic Agent, see script output for error."
|
||||
fail "Failed to install Elastic Agent"
|
||||
fi
|
||||
|
||||
waitForElasticAgentStatus() {
|
||||
local MAX_RETRIES=10
|
||||
local i=0
|
||||
echo -n "."
|
||||
elastic-agent status >/dev/null
|
||||
local ELASTIC_AGENT_STATUS_EXIT_CODE="$?"
|
||||
while [ "$ELASTIC_AGENT_STATUS_EXIT_CODE" -ne 0 ] && [ $i -le $MAX_RETRIES ]; do
|
||||
sleep 1
|
||||
echo -n "."
|
||||
elastic-agent status >/dev/null
|
||||
ELASTIC_AGENT_STATUS_EXIT_CODE="$?"
|
||||
((i++))
|
||||
done
|
||||
echo ""
|
||||
return $ELASTIC_AGENT_STATUS_EXIT_CODE
|
||||
}
|
||||
|
||||
echo "Checking Elastic Agent status"
|
||||
updateStepProgress "ea-status" "loading"
|
||||
waitForElasticAgentStatus
|
||||
if [ "$?" -ne 0 ]; then
|
||||
updateStepProgress "ea-status" "warning" "Unable to determine agent status"
|
||||
fi
|
||||
|
||||
# https://www.elastic.co/guide/en/fleet/current/elastic-agent-cmd-options.html#elastic-agent-status-command
|
||||
ELASTIC_AGENT_STATES=(STARTING CONFIGURING HEALTHY DEGRADED FAILED STOPPING UPGRADING ROLLBACK)
|
||||
|
||||
# Get elastic-agent status in json format | removing extra states in the json | finding "state":value | removing , | removing "state": | trimming the result
|
||||
ELASTIC_AGENT_STATE="$(elastic-agent status --output json | sed -n '/components/q;p' | grep state | sed 's/\(.*\),/\1 /' | sed 's/"state": //' | sed 's/[[:space:]]//g')"
|
||||
# Get elastic-agent status in json format | removing extra states in the json | finding "message":value | removing , | removing "message": | trimming the result | removing ""
|
||||
ELASTIC_AGENT_MESSAGE="$(elastic-agent status --output json | sed -n '/components/q;p' | grep message | sed 's/\(.*\),/\1 /' | sed 's/"message": //' | sed 's/[[:space:]]//g' | sed 's/\"//g')"
|
||||
# Get elastic-agent status in json format | removing extra ids in the json | finding "id":value | removing , | removing "id": | trimming the result | removing ""
|
||||
ELASTIC_AGENT_ID="$(elastic-agent status --output json | sed -n '/components/q;p' | grep \"id\" | sed 's/\(.*\),/\1 /' | sed 's/"id": //' | sed 's/[[:space:]]//g' | sed 's/\"//g')"
|
||||
if [ "${ELASTIC_AGENT_STATE}" = "2" ] && [ "${ELASTIC_AGENT_MESSAGE}" = "Running" ]; then
|
||||
echo "Elastic Agent running (id: ${ELASTIC_AGENT_ID})"
|
||||
echo "Download and save configuration to ${cfg}"
|
||||
updateStepProgress "ea-status" "complete" "" "{\"agentId\": \"${ELASTIC_AGENT_ID}\"}"
|
||||
else
|
||||
updateStepProgress "ea-status" "warning" "Expected agent status HEALTHY / Running but got ${ELASTIC_AGENT_STATES[ELASTIC_AGENT_STATE]} / ${ELASTIC_AGENT_MESSAGE}"
|
||||
fi
|
||||
|
||||
downloadElasticAgentConfig() {
|
||||
echo "Downloading elastic-agent.yml"
|
||||
updateStepProgress "ea-config" "loading"
|
||||
curl --request GET \
|
||||
--url "${API_ENDPOINT}/elastic_agent/config?onboardingId=${ONBOARDING_ID}" \
|
||||
--header "Authorization: ApiKey ${API_KEY_ENCODED}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "kbn-xsrf: true" \
|
||||
--header "x-elastic-internal-origin: Kibana" \
|
||||
--no-progress-meter \
|
||||
--output ${cfg}
|
||||
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo "Downloaded elastic-agent.yml"
|
||||
updateStepProgress "ea-config" "complete"
|
||||
else
|
||||
updateStepProgress "ea-config" "warning" "Failed to write elastic-agent.yml on host automatically, try manually setting the configuration"
|
||||
fail "Failed to download elastic-agent.yml"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "${AUTO_DOWNLOAD_CONFIG}" == "autoDownloadConfig=1" ]; then
|
||||
downloadElasticAgentConfig
|
||||
echo "Done with standalone Elastic Agent setup. Look for streaming logs to arrive in Kibana"
|
||||
else
|
||||
echo "Done with standalone Elastic Agent setup. Make sure to add your configuration to ${cfg}, then look for streaming logs to arrive in Kibana"
|
||||
fi
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* 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 * as t from 'io-ts';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { generateCustomLogsYml } from '../../../common/elastic_agent_logs';
|
||||
import { getAuthenticationAPIKey } from '../../lib/get_authentication_api_key';
|
||||
import { getFallbackESUrl } from '../../lib/get_fallback_urls';
|
||||
import { getObservabilityOnboardingFlow } from '../../lib/state';
|
||||
import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
|
||||
|
||||
const generateConfig = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'GET /internal/observability_onboarding/elastic_agent/config',
|
||||
params: t.type({
|
||||
query: t.type({ onboardingId: t.string }),
|
||||
}),
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'Authorization is checked by the Saved Object client',
|
||||
},
|
||||
},
|
||||
async handler(resources): Promise<string> {
|
||||
const {
|
||||
params: {
|
||||
query: { onboardingId },
|
||||
},
|
||||
core,
|
||||
plugins,
|
||||
request,
|
||||
services: { esLegacyConfigService },
|
||||
} = resources;
|
||||
const authApiKey = getAuthenticationAPIKey(request);
|
||||
|
||||
const coreStart = await core.start();
|
||||
const savedObjectsClient = coreStart.savedObjects.getScopedClient(request);
|
||||
|
||||
const elasticsearchUrl = plugins.cloud?.setup?.elasticsearchUrl
|
||||
? [plugins.cloud?.setup?.elasticsearchUrl]
|
||||
: await getFallbackESUrl(esLegacyConfigService);
|
||||
|
||||
const savedState = await getObservabilityOnboardingFlow({
|
||||
savedObjectsClient,
|
||||
savedObjectId: onboardingId,
|
||||
});
|
||||
|
||||
const yaml = generateCustomLogsYml({
|
||||
...savedState?.state,
|
||||
apiKey: authApiKey ? `${authApiKey?.apiKeyId}:${authApiKey?.apiKey}` : '$API_KEY',
|
||||
esHost: elasticsearchUrl,
|
||||
logfileId: `custom-logs-${uuidv4()}`,
|
||||
});
|
||||
|
||||
return yaml;
|
||||
},
|
||||
});
|
||||
|
||||
export const elasticAgentRouteRepository = {
|
||||
...generateConfig,
|
||||
};
|
|
@ -18,7 +18,6 @@ import { transformOutputToFullPolicyOutput } from '@kbn/fleet-plugin/server/serv
|
|||
import { OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT } from '../../../common/telemetry_events';
|
||||
import { getObservabilityOnboardingFlow, saveObservabilityOnboardingFlow } from '../../lib/state';
|
||||
import type { SavedObservabilityOnboardingFlow } from '../../saved_objects/observability_onboarding_status';
|
||||
import { ObservabilityOnboardingFlow } from '../../saved_objects/observability_onboarding_status';
|
||||
import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
|
||||
import { getHasLogs } from './get_has_logs';
|
||||
import { getKibanaUrl } from '../../lib/get_fallback_urls';
|
||||
|
@ -29,46 +28,6 @@ import { createInstallApiKey } from '../../lib/api_key/create_install_api_key';
|
|||
import { hasLogMonitoringPrivileges } from '../../lib/api_key/has_log_monitoring_privileges';
|
||||
import { makeTar, type Entry } from './make_tar';
|
||||
|
||||
const updateOnboardingFlowRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'PUT /internal/observability_onboarding/flow/{onboardingId}',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'Authorization is checked by the Saved Object client',
|
||||
},
|
||||
},
|
||||
params: t.type({
|
||||
path: t.type({
|
||||
onboardingId: t.string,
|
||||
}),
|
||||
body: t.partial({
|
||||
state: t.record(t.string, t.unknown),
|
||||
}),
|
||||
}),
|
||||
async handler(resources): Promise<{ onboardingId: string }> {
|
||||
const {
|
||||
params: {
|
||||
path: { onboardingId },
|
||||
body: { state },
|
||||
},
|
||||
core,
|
||||
request,
|
||||
} = resources;
|
||||
const coreStart = await core.start();
|
||||
const savedObjectsClient = coreStart.savedObjects.getScopedClient(request);
|
||||
const { id } = await saveObservabilityOnboardingFlow({
|
||||
savedObjectsClient,
|
||||
savedObjectId: onboardingId,
|
||||
observabilityOnboardingState: {
|
||||
type: 'logFiles',
|
||||
state,
|
||||
progress: {},
|
||||
} as ObservabilityOnboardingFlow,
|
||||
});
|
||||
return { onboardingId: id };
|
||||
},
|
||||
});
|
||||
|
||||
const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'POST /internal/observability_onboarding/flow/{id}/step/{name}',
|
||||
security: {
|
||||
|
@ -210,10 +169,6 @@ const getProgressRoute = createObservabilityOnboardingServerRoute({
|
|||
* Elastic agent.
|
||||
*
|
||||
* If the user does not have all necessary privileges a 403 Forbidden response is returned.
|
||||
*
|
||||
* This endpoint differs from the existing `POST /internal/observability_onboarding/logs/flow`
|
||||
* endpoint in that it caters for the auto-detect flow where integrations are detected and installed
|
||||
* on the host system, rather than in the Kibana UI.
|
||||
*/
|
||||
const createFlowRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'POST /internal/observability_onboarding/flow',
|
||||
|
@ -674,7 +629,6 @@ function generateAgentConfigTar(output: Output, installedIntegrations: Installed
|
|||
|
||||
export const flowRouteRepository = {
|
||||
...createFlowRoute,
|
||||
...updateOnboardingFlowRoute,
|
||||
...stepProgressUpdateRoute,
|
||||
...getProgressRoute,
|
||||
...integrationsInstallRoute,
|
||||
|
|
|
@ -5,19 +5,17 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import type { EndpointOf, ServerRouteRepository } from '@kbn/server-route-repository';
|
||||
import { elasticAgentRouteRepository } from './elastic_agent/route';
|
||||
import { flowRouteRepository } from './flow/route';
|
||||
import { kubernetesOnboardingRouteRepository } from './kubernetes/route';
|
||||
import { logsOnboardingRouteRepository } from './logs/route';
|
||||
import { firehoseOnboardingRouteRepository } from './firehose/route';
|
||||
import { otelHostOnboardingRouteRepository } from './otel_host/route';
|
||||
|
||||
function getTypedObservabilityOnboardingServerRouteRepository() {
|
||||
const repository = {
|
||||
...flowRouteRepository,
|
||||
...logsOnboardingRouteRepository,
|
||||
...elasticAgentRouteRepository,
|
||||
...kubernetesOnboardingRouteRepository,
|
||||
...firehoseOnboardingRouteRepository,
|
||||
...otelHostOnboardingRouteRepository,
|
||||
};
|
||||
|
||||
return repository;
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
* 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 * as t from 'io-ts';
|
||||
import Boom from '@hapi/boom';
|
||||
import { ElasticAgentVersionInfo } from '../../../common/types';
|
||||
import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
|
||||
import { getFallbackESUrl } from '../../lib/get_fallback_urls';
|
||||
import { getKibanaUrl } from '../../lib/get_fallback_urls';
|
||||
import { getAgentVersionInfo } from '../../lib/get_agent_version';
|
||||
import { saveObservabilityOnboardingFlow } from '../../lib/state';
|
||||
import { createShipperApiKey } from '../../lib/api_key/create_shipper_api_key';
|
||||
import { ObservabilityOnboardingFlow } from '../../saved_objects/observability_onboarding_status';
|
||||
import { hasLogMonitoringPrivileges } from '../../lib/api_key/has_log_monitoring_privileges';
|
||||
import { createManagedOtlpServiceApiKey } from '../../lib/api_key/create_managed_otlp_service_api_key';
|
||||
import { getManagedOtlpServiceUrl } from '../../lib/get_managed_otlp_service_url';
|
||||
|
||||
const logMonitoringPrivilegesRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'GET /internal/observability_onboarding/logs/setup/privileges',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route has custom authorization logic using Elasticsearch client',
|
||||
},
|
||||
},
|
||||
handler: async (resources): Promise<{ hasPrivileges: boolean }> => {
|
||||
const { context } = resources;
|
||||
|
||||
const {
|
||||
elasticsearch: { client },
|
||||
} = await context.core;
|
||||
|
||||
const hasPrivileges = await hasLogMonitoringPrivileges(client.asCurrentUser);
|
||||
|
||||
return { hasPrivileges };
|
||||
},
|
||||
});
|
||||
|
||||
const installShipperSetupRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'GET /internal/observability_onboarding/logs/setup/environment',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: "This route only reads cluster's metadata and does not require authorization",
|
||||
},
|
||||
},
|
||||
async handler(resources): Promise<{
|
||||
apiEndpoint: string;
|
||||
scriptDownloadUrl: string;
|
||||
elasticAgentVersionInfo: ElasticAgentVersionInfo;
|
||||
elasticsearchUrl: string[];
|
||||
managedOtlpServiceUrl: string;
|
||||
}> {
|
||||
const {
|
||||
core,
|
||||
plugins,
|
||||
kibanaVersion,
|
||||
services: { esLegacyConfigService },
|
||||
} = resources;
|
||||
|
||||
const fleetPluginStart = await plugins.fleet.start();
|
||||
const elasticAgentVersionInfo = await getAgentVersionInfo(fleetPluginStart, kibanaVersion);
|
||||
const kibanaUrl = getKibanaUrl(core.setup, plugins.cloud?.setup);
|
||||
const scriptDownloadUrl = new URL(
|
||||
core.setup.http.staticAssets.getPluginAssetHref('standalone_agent_setup.sh'),
|
||||
kibanaUrl
|
||||
).toString();
|
||||
|
||||
const apiEndpoint = new URL(`${kibanaUrl}/internal/observability_onboarding`).toString();
|
||||
|
||||
const elasticsearchUrl = plugins.cloud?.setup?.elasticsearchUrl
|
||||
? [plugins.cloud?.setup?.elasticsearchUrl]
|
||||
: await getFallbackESUrl(esLegacyConfigService);
|
||||
|
||||
return {
|
||||
apiEndpoint,
|
||||
elasticsearchUrl,
|
||||
scriptDownloadUrl,
|
||||
elasticAgentVersionInfo,
|
||||
managedOtlpServiceUrl: await getManagedOtlpServiceUrl(resources),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const createAPIKeyRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'POST /internal/observability_onboarding/otel/api_key',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route has custom authorization logic using Elasticsearch client',
|
||||
},
|
||||
},
|
||||
params: t.type({}),
|
||||
async handler({ context, config }): Promise<{ apiKeyEncoded: string }> {
|
||||
const {
|
||||
elasticsearch: { client },
|
||||
} = await context.core;
|
||||
|
||||
const hasPrivileges = await hasLogMonitoringPrivileges(client.asCurrentUser);
|
||||
if (!hasPrivileges) {
|
||||
throw Boom.forbidden('Insufficient permissions to create shipper API key');
|
||||
}
|
||||
|
||||
const timestamp = new Date().toISOString();
|
||||
const { encoded: apiKeyEncoded } = config.serverless.enabled
|
||||
? await createManagedOtlpServiceApiKey(client.asCurrentUser, `ingest-otel-host-${timestamp}`)
|
||||
: await createShipperApiKey(client.asCurrentUser, `otel-logs-${timestamp}`);
|
||||
|
||||
return { apiKeyEncoded };
|
||||
},
|
||||
});
|
||||
|
||||
const createFlowRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'POST /internal/observability_onboarding/logs/flow',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'Authorization is checked by the Saved Object client and Elasticsearch client',
|
||||
},
|
||||
},
|
||||
params: t.type({
|
||||
body: t.intersection([
|
||||
t.type({
|
||||
name: t.string,
|
||||
}),
|
||||
t.type({
|
||||
type: t.literal('logFiles'),
|
||||
}),
|
||||
t.partial({
|
||||
state: t.record(t.string, t.unknown),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
async handler(resources): Promise<{ apiKeyEncoded: string; onboardingId: string }> {
|
||||
const {
|
||||
context,
|
||||
params: {
|
||||
body: { name, type, state },
|
||||
},
|
||||
core,
|
||||
request,
|
||||
} = resources;
|
||||
const coreStart = await core.start();
|
||||
const {
|
||||
elasticsearch: { client },
|
||||
} = await context.core;
|
||||
const { encoded: apiKeyEncoded } = await createShipperApiKey(
|
||||
client.asCurrentUser,
|
||||
`standalone_agent_logs_onboarding_${name}`
|
||||
);
|
||||
|
||||
const savedObjectsClient = coreStart.savedObjects.getScopedClient(request);
|
||||
|
||||
const { id } = await saveObservabilityOnboardingFlow({
|
||||
savedObjectsClient,
|
||||
observabilityOnboardingState: {
|
||||
type,
|
||||
state: state as ObservabilityOnboardingFlow['state'],
|
||||
progress: {},
|
||||
},
|
||||
});
|
||||
|
||||
return { apiKeyEncoded, onboardingId: id };
|
||||
},
|
||||
});
|
||||
|
||||
export const logsOnboardingRouteRepository = {
|
||||
...logMonitoringPrivilegesRoute,
|
||||
...installShipperSetupRoute,
|
||||
...createFlowRoute,
|
||||
...createAPIKeyRoute,
|
||||
};
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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 Boom from '@hapi/boom';
|
||||
import { ElasticAgentVersionInfo } from '../../../common/types';
|
||||
import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
|
||||
import { getFallbackESUrl } from '../../lib/get_fallback_urls';
|
||||
import { getAgentVersionInfo } from '../../lib/get_agent_version';
|
||||
import { createShipperApiKey } from '../../lib/api_key/create_shipper_api_key';
|
||||
import { hasLogMonitoringPrivileges } from '../../lib/api_key/has_log_monitoring_privileges';
|
||||
import { createManagedOtlpServiceApiKey } from '../../lib/api_key/create_managed_otlp_service_api_key';
|
||||
import { getManagedOtlpServiceUrl } from '../../lib/get_managed_otlp_service_url';
|
||||
|
||||
const setupFlowRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'POST /internal/observability_onboarding/otel_host/setup',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'This route has custom authorization logic using Elasticsearch client',
|
||||
},
|
||||
},
|
||||
async handler(resources): Promise<{
|
||||
elasticAgentVersionInfo: ElasticAgentVersionInfo;
|
||||
elasticsearchUrl: string;
|
||||
apiKeyEncoded: string;
|
||||
managedOtlpServiceUrl: string;
|
||||
}> {
|
||||
const {
|
||||
context,
|
||||
config,
|
||||
plugins,
|
||||
kibanaVersion,
|
||||
services: { esLegacyConfigService },
|
||||
} = resources;
|
||||
const {
|
||||
elasticsearch: { client },
|
||||
} = await context.core;
|
||||
|
||||
const hasPrivileges = await hasLogMonitoringPrivileges(client.asCurrentUser);
|
||||
if (!hasPrivileges) {
|
||||
throw Boom.forbidden('Insufficient permissions to create API key');
|
||||
}
|
||||
|
||||
const fleetPluginStart = await plugins.fleet.start();
|
||||
const elasticAgentVersionInfo = await getAgentVersionInfo(fleetPluginStart, kibanaVersion);
|
||||
|
||||
const elasticsearchUrlList = plugins.cloud?.setup?.elasticsearchUrl
|
||||
? [plugins.cloud?.setup?.elasticsearchUrl]
|
||||
: await getFallbackESUrl(esLegacyConfigService);
|
||||
|
||||
const timestamp = new Date().toISOString();
|
||||
const { encoded: apiKeyEncoded } = config.serverless.enabled
|
||||
? await createManagedOtlpServiceApiKey(client.asCurrentUser, `ingest-otel-host-${timestamp}`)
|
||||
: await createShipperApiKey(client.asCurrentUser, `otel-host-${timestamp}`);
|
||||
|
||||
return {
|
||||
elasticsearchUrl: elasticsearchUrlList.length > 0 ? elasticsearchUrlList[0] : '',
|
||||
elasticAgentVersionInfo,
|
||||
apiKeyEncoded,
|
||||
managedOtlpServiceUrl: await getManagedOtlpServiceUrl(resources),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const otelHostOnboardingRouteRepository = {
|
||||
...setupFlowRoute,
|
||||
};
|
|
@ -21,7 +21,7 @@ export interface LogFilesState {
|
|||
|
||||
type ObservabilityOnboardingFlowState = LogFilesState | undefined;
|
||||
|
||||
type ObservabilityOnboardingType = 'logFiles' | 'autoDetect' | 'kubernetes';
|
||||
type ObservabilityOnboardingType = 'autoDetect';
|
||||
|
||||
export interface ObservabilityOnboardingFlow {
|
||||
type: ObservabilityOnboardingType;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
"@kbn/security-plugin",
|
||||
"@kbn/std",
|
||||
"@kbn/use-tracked-promise",
|
||||
"@kbn/custom-integrations",
|
||||
"@kbn/share-plugin",
|
||||
"@kbn/deeplinks-observability",
|
||||
"@kbn/fleet-plugin",
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* 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 const FIELD_VALIDATION = {
|
||||
INTEGRATION_NAME_LOWERCASE: 'An integration name should be lowercase.',
|
||||
DATASET_NAME_LOWERCASE: 'A dataset name should be lowercase.',
|
||||
};
|
|
@ -54,5 +54,3 @@ export const test = base.extend<ExtendedScoutTestFixtures, ExtendedScoutWorkerFi
|
|||
});
|
||||
|
||||
export const generateIntegrationName = (name: string) => `${name}_${uuidv4().slice(0, 5)}`;
|
||||
|
||||
export * as assertionMessages from './assertion_messages';
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* 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 { expect } from '@kbn/scout-oblt';
|
||||
import { generateIntegrationName, test } from '../../fixtures';
|
||||
|
||||
test.describe(
|
||||
'Observability Onboarding - Custom Integration',
|
||||
{ tag: ['@ess', '@svlOblt'] },
|
||||
() => {
|
||||
const integrationName = generateIntegrationName('mylogs');
|
||||
const logsFilePath = `${integrationName}.log`;
|
||||
|
||||
test.beforeEach(async ({ browserAuth, pageObjects: { customLogs } }) => {
|
||||
await browserAuth.loginAsAdmin();
|
||||
await customLogs.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async ({ apiServices }) => {
|
||||
await apiServices.fleet.integration.delete(integrationName);
|
||||
});
|
||||
|
||||
test('should be installed, show API Key and correct instructions', async ({
|
||||
pageObjects: { customLogs },
|
||||
page,
|
||||
}) => {
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await expect(customLogs.integrationNameInput).toHaveValue(integrationName);
|
||||
await expect(customLogs.datasetNameInput).toHaveValue(integrationName);
|
||||
await expect(customLogs.serviceNameInput).toHaveValue('');
|
||||
|
||||
await customLogs.continueButton.click();
|
||||
await expect(
|
||||
customLogs.customIntegrationInstalledCallout,
|
||||
`'mylogs integration installed' should be displayed`
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
customLogs.apiKeyCreatedCallout,
|
||||
`'API Key created' should be displayed`
|
||||
).toBeVisible();
|
||||
|
||||
// validate default 'Install the Elastic Agent' instructions
|
||||
await expect(page.testSubj.locator('linux-tar')).toHaveAttribute('aria-pressed', 'true');
|
||||
await expect(customLogs.autoDownloadConfigurationToggle).not.toBeChecked();
|
||||
await expect(customLogs.installCodeSnippet).toBeVisible();
|
||||
|
||||
await customLogs.selectPlatform('macos');
|
||||
await expect(customLogs.autoDownloadConfigurationToggle).not.toBeChecked();
|
||||
await expect(customLogs.installCodeSnippet).toBeVisible();
|
||||
|
||||
await customLogs.selectPlatform('windows');
|
||||
await expect(customLogs.autoDownloadConfigurationToggle).toBeDisabled();
|
||||
await expect(customLogs.windowsInstallElasticAgentDocLink).toBeVisible();
|
||||
await expect(customLogs.installCodeSnippet).toBeHidden();
|
||||
await expect(
|
||||
customLogs.configureElasticAgentStep.getByText('Step 2 is disabled')
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('should update instructions when automatic config download toggled', async ({
|
||||
pageObjects: { customLogs },
|
||||
}) => {
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await customLogs.continueButton.click();
|
||||
|
||||
await customLogs.autoDownloadConfigurationToggle.click();
|
||||
await expect(customLogs.autoDownloadConfigurationCallout).toBeVisible();
|
||||
await expect(customLogs.installCodeSnippet).toContainText('autoDownloadConfig=1');
|
||||
|
||||
await customLogs.selectPlatform('macos');
|
||||
await expect(customLogs.autoDownloadConfigurationCallout).toBeVisible();
|
||||
await expect(customLogs.installCodeSnippet).toContainText('autoDownloadConfig=1');
|
||||
|
||||
await customLogs.autoDownloadConfigurationToggle.click();
|
||||
await expect(customLogs.installCodeSnippet).not.toContainText('autoDownloadConfig=1');
|
||||
});
|
||||
}
|
||||
);
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* 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 { expect } from '@kbn/scout-oblt';
|
||||
import { assertionMessages, generateIntegrationName, test } from '../../fixtures';
|
||||
|
||||
test.describe(
|
||||
'Observability Onboarding - Custom logs configuration',
|
||||
{ tag: ['@ess', '@svlOblt'] },
|
||||
() => {
|
||||
const logsFilePath = `${generateIntegrationName('mylogs')}.log`;
|
||||
|
||||
test.beforeEach(async ({ browserAuth, pageObjects: { customLogs } }) => {
|
||||
await browserAuth.loginAsAdmin();
|
||||
await customLogs.goto();
|
||||
});
|
||||
|
||||
test('should navigate to the onboarding home page when the back button clicked', async ({
|
||||
pageObjects: { customLogs },
|
||||
page,
|
||||
}) => {
|
||||
await customLogs.clickBackButton();
|
||||
expect(page.url()).toContain('/app/observabilityOnboarding');
|
||||
});
|
||||
|
||||
test(`should allow multiple entries for Log File Path`, async ({
|
||||
pageObjects: { customLogs },
|
||||
}) => {
|
||||
await expect(
|
||||
customLogs.getLogFilePathInputField(0),
|
||||
'Log File Path should be empty'
|
||||
).toHaveValue('');
|
||||
await expect(
|
||||
customLogs.continueButton,
|
||||
'Continue button should be disabled when Log File Path is not set'
|
||||
).toBeDisabled();
|
||||
await customLogs.addLogFilePathButton.click();
|
||||
await expect(customLogs.logFilePathList).toHaveCount(2);
|
||||
|
||||
await customLogs.logFilePathDeleteButton(1).click();
|
||||
await expect(customLogs.logFilePathList).toHaveCount(1);
|
||||
});
|
||||
|
||||
test(`should allow updating Advanced Settings`, async ({ pageObjects: { customLogs } }) => {
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await expect(customLogs.advancedSettingsContent).toBeHidden();
|
||||
await customLogs.clickAdvancedSettingsButton();
|
||||
await expect(
|
||||
customLogs.advancedSettingsContent,
|
||||
'Advanced Settings should be opened'
|
||||
).toBeVisible();
|
||||
await expect(customLogs.namespaceInput).toHaveValue('default');
|
||||
|
||||
await customLogs.namespaceInput.fill('');
|
||||
await expect(
|
||||
customLogs.continueButton,
|
||||
'Continue button should be disabled when Namespace is empty'
|
||||
).toBeDisabled();
|
||||
|
||||
await customLogs.namespaceInput.fill('default');
|
||||
await expect(customLogs.customConfigInput).toHaveValue('');
|
||||
await expect(customLogs.continueButton).toBeEnabled();
|
||||
|
||||
await customLogs.clickAdvancedSettingsButton();
|
||||
await expect(
|
||||
customLogs.advancedSettingsContent,
|
||||
'Advanced Settings should be closed'
|
||||
).toBeHidden();
|
||||
});
|
||||
|
||||
test('should validate Integration Name field', async ({
|
||||
pageObjects: { customLogs },
|
||||
page,
|
||||
}) => {
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
|
||||
await customLogs.integrationNameInput.fill('');
|
||||
await expect(customLogs.continueButton).toBeDisabled();
|
||||
|
||||
await customLogs.integrationNameInput.fill('hello$world');
|
||||
await expect(customLogs.integrationNameInput).toHaveValue('hello_world');
|
||||
|
||||
await customLogs.integrationNameInput.fill('H3llowOrld');
|
||||
await expect(
|
||||
page.getByText(assertionMessages.FIELD_VALIDATION.INTEGRATION_NAME_LOWERCASE)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('should validate DataSet Name field', async ({ pageObjects: { customLogs }, page }) => {
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await customLogs.datasetNameInput.fill('');
|
||||
await expect(customLogs.continueButton).toBeDisabled();
|
||||
|
||||
await customLogs.datasetNameInput.fill('hello$world');
|
||||
await expect(customLogs.datasetNameInput).toHaveValue('hello_world');
|
||||
|
||||
await customLogs.datasetNameInput.fill('H3llowOrld');
|
||||
await expect(
|
||||
page.getByText(assertionMessages.FIELD_VALIDATION.DATASET_NAME_LOWERCASE)
|
||||
).toBeVisible();
|
||||
});
|
||||
}
|
||||
);
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* 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 { expect } from '@kbn/scout-oblt';
|
||||
import { generateIntegrationName, test } from '../../fixtures';
|
||||
|
||||
test.describe(
|
||||
'Observability Onboarding - Custom Integration Error',
|
||||
{ tag: ['@ess', '@svlOblt'] },
|
||||
() => {
|
||||
const integrationName = generateIntegrationName('mylogs');
|
||||
const logsFilePath = `${integrationName}.log`;
|
||||
|
||||
test.afterEach(async ({ apiServices }) => {
|
||||
await apiServices.fleet.integration.delete(integrationName);
|
||||
});
|
||||
|
||||
test('should be displayed when user has no previleges', async ({
|
||||
browserAuth,
|
||||
pageObjects: { customLogs },
|
||||
}) => {
|
||||
await browserAuth.loginAsPrivilegedUser();
|
||||
await customLogs.goto();
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await customLogs.continueButton.click();
|
||||
await expect(
|
||||
customLogs.customIntegrationInstalledCallout,
|
||||
`'mylogs integration installed' should be displayed`
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
customLogs.apiKeyPrivilegesErrorCallout,
|
||||
`'User does not have permissions to create API key' should be displayed`
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('should be displayed when API Key creation failed', async ({
|
||||
browserAuth,
|
||||
pageObjects: { customLogs },
|
||||
page,
|
||||
}) => {
|
||||
await page.route('**/observability_onboarding/logs/flow', (route) => {
|
||||
route.fulfill({
|
||||
status: 500,
|
||||
body: JSON.stringify({
|
||||
message: 'Internal error',
|
||||
}),
|
||||
});
|
||||
});
|
||||
await browserAuth.loginAsAdmin();
|
||||
await customLogs.goto();
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await customLogs.continueButton.click();
|
||||
await expect(
|
||||
customLogs.customIntegrationInstalledCallout,
|
||||
`'mylogs integration installed' should be displayed`
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
customLogs.apiKeyCreateErrorCallout,
|
||||
`'Failed to create API Key' should be displayed`
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('should be displayed when integration failed', async ({
|
||||
browserAuth,
|
||||
pageObjects: { customLogs },
|
||||
page,
|
||||
kbnUrl,
|
||||
}) => {
|
||||
await page.route(kbnUrl.get('/api/fleet/epm/custom_integrations'), (route) => {
|
||||
route.fulfill({
|
||||
status: 500,
|
||||
json: {
|
||||
message: 'Internal error',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
await browserAuth.loginAsAdmin();
|
||||
await customLogs.goto();
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await customLogs.continueButton.click();
|
||||
|
||||
await expect(customLogs.customIntegrationErrorCallout).toBeVisible();
|
||||
});
|
||||
|
||||
test('should be displayed when integration with the same name exists', async ({
|
||||
browserAuth,
|
||||
pageObjects: { customLogs },
|
||||
apiServices,
|
||||
page,
|
||||
}) => {
|
||||
await apiServices.fleet.integration.install(integrationName);
|
||||
await browserAuth.loginAsAdmin();
|
||||
await customLogs.goto();
|
||||
|
||||
await customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await customLogs.continueButton.click();
|
||||
|
||||
const errorMessage = `Failed to create the integration as an installation with the name ${integrationName} already exists.`;
|
||||
await expect(page.getByText(errorMessage)).toBeVisible();
|
||||
});
|
||||
}
|
||||
);
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
* 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 { expect, Locator } from '@kbn/scout-oblt';
|
||||
import { generateIntegrationName, test } from '../../fixtures';
|
||||
|
||||
const checkAgentStatusUpdated = async (locator: Locator, status: string) =>
|
||||
expect(locator.getByText(status)).toBeVisible();
|
||||
|
||||
test.describe('Observability Onboarding - Elastic Agent', { tag: ['@ess', '@svlOblt'] }, () => {
|
||||
const integrationName = generateIntegrationName('mylogs');
|
||||
const logsFilePath = `${integrationName}.log`;
|
||||
let onboardingId: string;
|
||||
|
||||
test.beforeEach(async ({ browserAuth, pageObjects, page }) => {
|
||||
await page.route('**/observability_onboarding/logs/flow', async (route) => {
|
||||
const response = await route.fetch();
|
||||
const body = await response.json();
|
||||
|
||||
onboardingId = body.onboardingId;
|
||||
|
||||
await route.fulfill({ response });
|
||||
});
|
||||
|
||||
// login and create custom integration
|
||||
await browserAuth.loginAsAdmin();
|
||||
await pageObjects.customLogs.goto();
|
||||
await pageObjects.customLogs.getLogFilePathInputField(0).fill(logsFilePath);
|
||||
await pageObjects.customLogs.continueButton.click();
|
||||
await pageObjects.customLogs.apiKeyCreatedCallout.waitFor({ state: 'visible' });
|
||||
});
|
||||
|
||||
test.afterEach(async ({ apiServices }) => {
|
||||
await apiServices.fleet.integration.delete(integrationName);
|
||||
});
|
||||
|
||||
test('should be installed sucessfully', async ({ pageObjects: { customLogs }, apiServices }) => {
|
||||
// downloading agent
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-download',
|
||||
'loading'
|
||||
);
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('loading'),
|
||||
'Downloading Elastic Agent'
|
||||
);
|
||||
// downloading agent failed
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-download',
|
||||
'danger'
|
||||
);
|
||||
await expect(customLogs.getStepStatusLocator('danger'), 'Download Elastic Agent').toBeVisible();
|
||||
// downloading agent completed
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-download',
|
||||
'complete'
|
||||
);
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('complete'),
|
||||
'Elastic Agent downloaded'
|
||||
);
|
||||
|
||||
// extracting agent
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-extract',
|
||||
'loading'
|
||||
);
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('loading'),
|
||||
'Extracting Elastic Agent'
|
||||
);
|
||||
// extracting agent completed
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-extract',
|
||||
'complete'
|
||||
);
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('complete'),
|
||||
'Elastic Agent extracted'
|
||||
);
|
||||
|
||||
// installing agent failed
|
||||
await apiServices.onboarding.updateInstallationStepStatus(onboardingId, 'ea-install', 'danger');
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('danger'),
|
||||
'Install Elastic Agent'
|
||||
);
|
||||
// installing agent completed
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-install',
|
||||
'complete'
|
||||
);
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('complete'),
|
||||
'Elastic Agent installed'
|
||||
);
|
||||
|
||||
// agent connecting
|
||||
await apiServices.onboarding.updateInstallationStepStatus(onboardingId, 'ea-status', 'loading');
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('loading'),
|
||||
'Connecting to the Elastic Agent'
|
||||
);
|
||||
await expect(customLogs.getCheckLogsStepLocator('incomplete')).toBeVisible();
|
||||
await expect(customLogs.checkLogsStepMessage).toHaveText('Ship logs to Elastic Observability');
|
||||
// agent connected
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-status',
|
||||
'complete',
|
||||
{
|
||||
agentId: 'test-agent-id',
|
||||
}
|
||||
);
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('complete'),
|
||||
'Connected to the Elastic Agent'
|
||||
);
|
||||
});
|
||||
|
||||
test('should be configured sucessfully for Linux and wait for logs', async ({
|
||||
pageObjects: { customLogs },
|
||||
apiServices,
|
||||
}) => {
|
||||
// install and connect agent for linux
|
||||
await customLogs.autoDownloadConfigurationToggle.click();
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-download',
|
||||
'complete'
|
||||
);
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-extract',
|
||||
'complete'
|
||||
);
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-install',
|
||||
'complete'
|
||||
);
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-status',
|
||||
'complete',
|
||||
{
|
||||
agentId: 'test-agent-id',
|
||||
}
|
||||
);
|
||||
|
||||
await apiServices.onboarding.updateInstallationStepStatus(onboardingId, 'ea-config', 'loading');
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('loading'),
|
||||
'Downloading Elastic Agent config'
|
||||
);
|
||||
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-config',
|
||||
'complete'
|
||||
);
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('complete'),
|
||||
'Elastic Agent config written to /opt/Elastic/Agent/elastic-agent.yml'
|
||||
);
|
||||
|
||||
await expect(customLogs.getCheckLogsStepLocator('loading')).toBeVisible();
|
||||
await expect(customLogs.checkLogsStepMessage).toHaveText('Waiting for logs to be shipped...');
|
||||
});
|
||||
|
||||
test('should be configured sucessfully for MacOS and wait for logs', async ({
|
||||
pageObjects: { customLogs },
|
||||
apiServices,
|
||||
}) => {
|
||||
// install and connect agent for macos
|
||||
await customLogs.selectPlatform('macos');
|
||||
await customLogs.autoDownloadConfigurationToggle.click();
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-download',
|
||||
'complete'
|
||||
);
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-extract',
|
||||
'complete'
|
||||
);
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-install',
|
||||
'complete'
|
||||
);
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-status',
|
||||
'complete',
|
||||
{
|
||||
agentId: 'test-agent-id',
|
||||
}
|
||||
);
|
||||
|
||||
await apiServices.onboarding.updateInstallationStepStatus(
|
||||
onboardingId,
|
||||
'ea-config',
|
||||
'complete'
|
||||
);
|
||||
await checkAgentStatusUpdated(
|
||||
customLogs.getStepStatusLocator('complete'),
|
||||
'Elastic Agent config written to /Library/Elastic/Agent/elastic-agent.yml'
|
||||
);
|
||||
|
||||
await expect(customLogs.getCheckLogsStepLocator('loading')).toBeVisible();
|
||||
await expect(customLogs.checkLogsStepMessage).toHaveText('Waiting for logs to be shipped...');
|
||||
});
|
||||
|
||||
test('should ship logs to Elastic', async ({ page, pageObjects: { customLogs } }) => {
|
||||
await page.route('**/progress', (route) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
body: JSON.stringify({
|
||||
progress: {
|
||||
'ea-download': { status: 'complete' },
|
||||
'ea-extract': { status: 'complete' },
|
||||
'ea-install': { status: 'complete' },
|
||||
'ea-status': { status: 'complete' },
|
||||
'ea-config': { status: 'complete' },
|
||||
'logs-ingest': { status: 'complete' },
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
await expect(customLogs.getCheckLogsStepLocator('complete')).toBeVisible();
|
||||
await expect(customLogs.checkLogsStepMessage).toHaveText('Logs are being shipped!');
|
||||
|
||||
await customLogs.exploreLogsButton.click();
|
||||
await expect(page).toHaveURL(/\/app\/discover/);
|
||||
});
|
||||
});
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE } from '@kbn/observability-onboarding-plugin/server/saved_objects/observability_onboarding_status';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { SupertestWithRoleScopeType } from '../../../services';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const roleScopedSupertest = getService('roleScopedSupertest');
|
||||
let viewerClient: SupertestWithRoleScopeType;
|
||||
let adminClient: SupertestWithRoleScopeType;
|
||||
|
||||
describe('Creating onboarding logs flow', () => {
|
||||
before(async () => {
|
||||
viewerClient = await roleScopedSupertest.getSupertestWithRoleScope('viewer', {
|
||||
withInternalHeaders: true,
|
||||
useCookieHeader: true,
|
||||
});
|
||||
adminClient = await roleScopedSupertest.getSupertestWithRoleScope('admin', {
|
||||
withInternalHeaders: true,
|
||||
useCookieHeader: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('fails with a 500 error when missing privileges', async () => {
|
||||
const response = await viewerClient
|
||||
.post('/internal/observability_onboarding/logs/flow')
|
||||
.send({
|
||||
type: 'logFiles',
|
||||
name: 'name',
|
||||
state: {},
|
||||
});
|
||||
|
||||
expect(response.statusCode).to.be(500);
|
||||
expect(response.body.message).to.contain('unauthorized');
|
||||
});
|
||||
|
||||
it('returns a flow id and apiKey encoded', async () => {
|
||||
const state = {
|
||||
datasetName: 'my-dataset',
|
||||
serviceName: 'my-service',
|
||||
namespace: 'my-namespace',
|
||||
logFilePaths: ['my-service-logs.log'],
|
||||
};
|
||||
|
||||
const response = await adminClient.post('/internal/observability_onboarding/logs/flow').send({
|
||||
type: 'logFiles',
|
||||
name: 'name',
|
||||
state,
|
||||
});
|
||||
|
||||
expect(response.statusCode).to.be(200);
|
||||
expect(response.body.apiKeyEncoded).to.not.empty();
|
||||
expect(response.body.onboardingId).to.not.empty();
|
||||
});
|
||||
|
||||
it('saves the expected state for logFiles', async () => {
|
||||
const state = {
|
||||
datasetName: 'my-dataset',
|
||||
serviceName: 'my-service',
|
||||
namespace: 'my-namespace',
|
||||
logFilePaths: ['my-service-logs.log'],
|
||||
};
|
||||
|
||||
const response = await adminClient.post('/internal/observability_onboarding/logs/flow').send({
|
||||
type: 'logFiles',
|
||||
name: 'name',
|
||||
state,
|
||||
});
|
||||
|
||||
const savedState = await kibanaServer.savedObjects.get({
|
||||
type: OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE,
|
||||
id: response.body.onboardingId,
|
||||
});
|
||||
|
||||
expect(savedState.attributes).to.be.eql({ type: 'logFiles', state, progress: {} });
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { load } from 'js-yaml';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { SupertestWithRoleScopeType } from '../../../services';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
const roleScopedSupertest = getService('roleScopedSupertest');
|
||||
let adminClient: SupertestWithRoleScopeType;
|
||||
|
||||
describe('Generate Elastic Agent configuration', () => {
|
||||
before(async () => {
|
||||
adminClient = await roleScopedSupertest.getSupertestWithRoleScope('admin', {
|
||||
withInternalHeaders: true,
|
||||
useCookieHeader: true,
|
||||
});
|
||||
});
|
||||
|
||||
it(`should return input properties empty when onboardingId doesn't exists`, async () => {
|
||||
const response = await adminClient
|
||||
.get('/internal/observability_onboarding/elastic_agent/config')
|
||||
.query({ onboardingId: 'my-onboarding-id' });
|
||||
|
||||
expect(response.status).to.be(200);
|
||||
|
||||
const ymlConfig = load(response.text);
|
||||
expect(ymlConfig.inputs[0].data_stream.namespace).to.be('');
|
||||
expect(ymlConfig.inputs[0].streams[0].data_stream.dataset).to.be('');
|
||||
expect(ymlConfig.inputs[0].streams[0].paths).to.be.empty();
|
||||
});
|
||||
|
||||
it('should return input properties configured when onboardingId exists', async () => {
|
||||
const datasetName = 'api-tests';
|
||||
const namespace = 'default';
|
||||
const logFilepath = '/my-logs.log';
|
||||
const serviceName = 'my-service';
|
||||
|
||||
const createFlowResponse = await adminClient
|
||||
.post('/internal/observability_onboarding/logs/flow')
|
||||
.send({
|
||||
type: 'logFiles',
|
||||
name: 'name',
|
||||
state: {
|
||||
datasetName,
|
||||
namespace,
|
||||
logFilePaths: [logFilepath],
|
||||
serviceName,
|
||||
},
|
||||
});
|
||||
|
||||
const onboardingId = createFlowResponse.body.onboardingId;
|
||||
|
||||
const response = await adminClient
|
||||
.get('/internal/observability_onboarding/elastic_agent/config')
|
||||
.query({ onboardingId });
|
||||
|
||||
expect(response.status).to.be(200);
|
||||
|
||||
const ymlConfig = load(response.text);
|
||||
expect(ymlConfig.inputs[0].data_stream.namespace).to.be(namespace);
|
||||
expect(ymlConfig.inputs[0].streams[0].data_stream.dataset).to.be(datasetName);
|
||||
expect(ymlConfig.inputs[0].streams[0].paths).to.be.eql([logFilepath]);
|
||||
expect(ymlConfig.inputs[0].streams[0].processors[0].add_fields.fields.name).to.be.eql(
|
||||
serviceName
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { type DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { type SupertestWithRoleScopeType } from '../../../services';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
const roleScopedSupertest = getService('roleScopedSupertest');
|
||||
|
||||
let viewerClientWithAPIKey: SupertestWithRoleScopeType;
|
||||
let adminClientWithAPIKey: SupertestWithRoleScopeType;
|
||||
|
||||
describe('Api Key privileges check', () => {
|
||||
before(async () => {
|
||||
viewerClientWithAPIKey = await roleScopedSupertest.getSupertestWithRoleScope('viewer', {
|
||||
withInternalHeaders: true,
|
||||
});
|
||||
adminClientWithAPIKey = await roleScopedSupertest.getSupertestWithRoleScope('admin', {
|
||||
withInternalHeaders: true,
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await viewerClientWithAPIKey.destroy();
|
||||
await adminClientWithAPIKey.destroy();
|
||||
});
|
||||
|
||||
it('returns false when user has reader privileges', async () => {
|
||||
const response = await viewerClientWithAPIKey.get(
|
||||
`/internal/observability_onboarding/logs/setup/privileges`
|
||||
);
|
||||
|
||||
expect(response.body.hasPrivileges).not.ok();
|
||||
});
|
||||
|
||||
it('returns true when user has admin privileges', async () => {
|
||||
const response = await adminClientWithAPIKey.get(
|
||||
`/internal/observability_onboarding/logs/setup/privileges`
|
||||
);
|
||||
|
||||
expect(response.body.hasPrivileges).ok();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -31,18 +31,12 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
|||
});
|
||||
|
||||
const createFlowResponse = await adminClient
|
||||
.post('/internal/observability_onboarding/logs/flow')
|
||||
.post('/internal/observability_onboarding/flow')
|
||||
.send({
|
||||
type: 'logFiles',
|
||||
name: 'name',
|
||||
state: {
|
||||
datasetName,
|
||||
namespace,
|
||||
logFilePaths: ['my-service.log'],
|
||||
},
|
||||
name: 'test-onboarding',
|
||||
});
|
||||
|
||||
onboardingId = createFlowResponse.body.onboardingId;
|
||||
onboardingId = createFlowResponse.body.onboardingFlow.id;
|
||||
});
|
||||
|
||||
it(`fails with a 404 error when onboardingId doesn't exists`, async () => {
|
||||
|
@ -54,17 +48,6 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
|||
expect(response.body.message).to.contain('onboarding session not found');
|
||||
});
|
||||
|
||||
it('should skip log verification and return log-ingest as incomplete when ea-status is not complete', async () => {
|
||||
const response = await adminClient.get(
|
||||
`/internal/observability_onboarding/flow/${onboardingId}/progress`
|
||||
);
|
||||
|
||||
expect(response.status).to.be(200);
|
||||
|
||||
const logsIngestProgress = response.body.progress['logs-ingest'];
|
||||
expect(logsIngestProgress).to.have.property('status', 'incomplete');
|
||||
});
|
||||
|
||||
describe('when ea-status is complete', () => {
|
||||
describe('should not skip logs verification', () => {
|
||||
const agentId = 'my-agent-id';
|
||||
|
|
|
@ -9,10 +9,7 @@ import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_cont
|
|||
|
||||
export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('Onboarding', () => {
|
||||
loadTestFile(require.resolve('./create_logs_onboarding_flow'));
|
||||
loadTestFile(require.resolve('./get_elastic_agent_config'));
|
||||
loadTestFile(require.resolve('./get_progress'));
|
||||
loadTestFile(require.resolve('./update_progress'));
|
||||
loadTestFile(require.resolve('./get_privileges'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -49,19 +49,12 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
|||
|
||||
beforeEach(async () => {
|
||||
const createFlowResponse = await adminClient
|
||||
.post('/internal/observability_onboarding/logs/flow')
|
||||
.post('/internal/observability_onboarding/flow')
|
||||
.send({
|
||||
type: 'logFiles',
|
||||
name: 'name',
|
||||
state: {
|
||||
datasetName: 'my-dataset',
|
||||
serviceName: 'my-service',
|
||||
namespace: 'my-namespace',
|
||||
logFilePaths: ['my-service.log'],
|
||||
},
|
||||
name: 'test-onboarding',
|
||||
});
|
||||
|
||||
onboardingId = createFlowResponse.body.onboardingId;
|
||||
onboardingId = createFlowResponse.body.onboardingFlow.id;
|
||||
|
||||
const savedState = await kibanaServer.savedObjects.get({
|
||||
type: OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE,
|
||||
|
|
|
@ -34,26 +34,18 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
registry.when('Get progress', { config: 'basic' }, () => {
|
||||
let onboardingId: string;
|
||||
const datasetName = 'api-tests';
|
||||
const namespace = 'default';
|
||||
|
||||
before(async () => {
|
||||
const req = await observabilityOnboardingApiClient.logMonitoringUser({
|
||||
endpoint: 'POST /internal/observability_onboarding/logs/flow',
|
||||
endpoint: 'POST /internal/observability_onboarding/flow',
|
||||
params: {
|
||||
body: {
|
||||
type: 'logFiles',
|
||||
name: 'name',
|
||||
state: {
|
||||
datasetName,
|
||||
namespace,
|
||||
logFilePaths: ['my-service.log'],
|
||||
},
|
||||
name: 'test-onboarding',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
onboardingId = req.body.onboardingId;
|
||||
onboardingId = req.body.onboardingFlow.id;
|
||||
});
|
||||
|
||||
describe('when missing required privileges', () => {
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import { MOCKED_KIBANA_URL, MOCKED_PUBLIC_BASE_URL } from '../../configs';
|
||||
|
||||
export default function ApiTest({ getService }: FtrProviderContext) {
|
||||
const registry = getService('registry');
|
||||
const observabilityOnboardingApiClient = getService('observabilityOnboardingApiClient');
|
||||
|
||||
async function callApiWithPrivileges() {
|
||||
return await observabilityOnboardingApiClient.logMonitoringUser({
|
||||
endpoint: 'GET /internal/observability_onboarding/logs/setup/environment',
|
||||
});
|
||||
}
|
||||
|
||||
registry.when('Install shipper setup', { config: 'basic' }, () => {
|
||||
it('returns apiEndpoint and scriptDownloadUrl prioritizing server.publicBaseUrl', async () => {
|
||||
const request = await callApiWithPrivileges();
|
||||
|
||||
expect(request.status).to.be(200);
|
||||
expect(request.body.apiEndpoint).to.be(
|
||||
`${MOCKED_PUBLIC_BASE_URL}/internal/observability_onboarding`
|
||||
);
|
||||
expect(request.body.scriptDownloadUrl).to.match(
|
||||
new RegExp(
|
||||
`${MOCKED_PUBLIC_BASE_URL}/.+?/plugins/observabilityOnboarding/assets/standalone_agent_setup.sh`,
|
||||
'i'
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
registry.when('Install shipper setup', { config: 'cloud' }, () => {
|
||||
it('returns apiEndpoint and scriptDownloadUrl prioritizing cloudId', async () => {
|
||||
const request = await callApiWithPrivileges();
|
||||
|
||||
expect(request.status).to.be(200);
|
||||
expect(request.body.apiEndpoint).to.be(
|
||||
`${MOCKED_KIBANA_URL}/internal/observability_onboarding`
|
||||
);
|
||||
expect(request.body.scriptDownloadUrl).to.match(
|
||||
new RegExp(
|
||||
`${MOCKED_KIBANA_URL}/.+?/plugins/observabilityOnboarding/assets/standalone_agent_setup.sh`,
|
||||
'i'
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { ObservabilityOnboardingApiClientKey } from '../../common/config';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
|
||||
export default function ApiTest({ getService }: FtrProviderContext) {
|
||||
const registry = getService('registry');
|
||||
const observabilityOnboardingApiClient = getService('observabilityOnboardingApiClient');
|
||||
|
||||
async function callApiAs(user: ObservabilityOnboardingApiClientKey) {
|
||||
return await observabilityOnboardingApiClient[user]({
|
||||
endpoint: 'GET /internal/observability_onboarding/logs/setup/privileges',
|
||||
});
|
||||
}
|
||||
|
||||
registry.when('Api Key privileges check', { config: 'basic' }, () => {
|
||||
describe('when missing required privileges', () => {
|
||||
it('returns false when user has no access privileges', async () => {
|
||||
const privileges = await callApiAs('noAccessUser');
|
||||
|
||||
expect(privileges.body.hasPrivileges).not.ok();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Reference in a new issue