Commit 0b5d06d9 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'ak/frontend-logs-to-core' into 'master'

Move logs to core (frontend)

See merge request gitlab-org/gitlab!26383
parents 86509ce3 3f61d636
......@@ -492,6 +492,41 @@ const Api = {
buildUrl(url) {
return joinPaths(gon.relative_url_root || '', url.replace(':version', gon.api_version));
},
/**
* Returns pods logs for an environment with an optional pod and container
*
* @param {Object} params
* @param {Object} param.environment - Environment object
* @param {string=} params.podName - Pod name, if not set the backend assumes a default one
* @param {string=} params.containerName - Container name, if not set the backend assumes a default one
* @param {string=} params.start - Starting date to query the logs in ISO format
* @param {string=} params.end - Ending date to query the logs in ISO format
* @returns {Promise} Axios promise for the result of a GET request of logs
*/
getPodLogs({ environment, podName, containerName, search, start, end }) {
const url = this.buildUrl(environment.logs_api_path);
const params = {};
if (podName) {
params.pod_name = podName;
}
if (containerName) {
params.container_name = containerName;
}
if (search) {
params.search = search;
}
if (start) {
params.start = start;
}
if (end) {
params.end = end;
}
return axios.get(url, { params });
},
};
export default Api;
import Api from 'ee/api';
import Api from '~/api';
import { backOff } from '~/lib/utils/common_utils';
import httpStatusCodes from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
......
import logsBundle from 'ee/logs';
import logsBundle from '~/logs';
document.addEventListener('DOMContentLoaded', logsBundle);
......@@ -357,3 +357,42 @@
}
}
}
.build-page-pod-logs {
.build-trace-container {
position: relative;
}
.build-trace {
@include build-trace();
}
.top-bar {
@include build-trace-top-bar($gl-line-height * 5);
.dropdown-menu-toggle {
width: 200px;
@include media-breakpoint-up(sm) {
width: 300px;
}
}
.controllers {
@include build-controllers(16px, flex-end, true, 2);
}
.refresh-control {
@include build-controllers(16px, flex-end, true, 0);
margin-left: 2px;
}
}
.btn-refresh svg {
top: 0;
}
.build-loader-animation {
@include build-loader-animation;
}
}
......@@ -41,4 +41,13 @@ module EnvironmentsHelper
"external-dashboard-url" => project.metrics_setting_external_dashboard_url
}
end
def environment_logs_data(project, environment)
{
"environment-name": environment.name,
"environments-path": project_environments_path(project, format: :json),
"environment-id": environment.id,
"cluster-applications-documentation-path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack')
}
end
end
......@@ -330,6 +330,10 @@ class Environment < ApplicationRecord
self.auto_stop_at = parsed_result.seconds.from_now
end
def elastic_stack_available?
!!deployment_platform&.cluster&.application_elastic_stack&.available?
end
private
def has_metrics_and_can_query?
......
......@@ -314,6 +314,7 @@ class ProjectPolicy < BasePolicy
enable :admin_operations
enable :read_deploy_token
enable :create_deploy_token
enable :read_pod_logs
end
rule { (mirror_available & can?(:admin_project)) | admin }.enable :admin_remote_mirror
......
......@@ -47,6 +47,22 @@ class EnvironmentEntity < Grape::Entity
environment.available? && can?(current_user, :stop_environment, environment)
end
expose :logs_path, if: -> (*) { can_read_pod_logs? } do |environment|
project_logs_path(environment.project, environment_name: environment.name)
end
expose :logs_api_path, if: -> (*) { can_read_pod_logs? } do |environment|
if environment.elastic_stack_available?
elasticsearch_project_logs_path(environment.project, environment_name: environment.name, format: :json)
else
k8s_project_logs_path(environment.project, environment_name: environment.name, format: :json)
end
end
expose :enable_advanced_logs_querying, if: -> (*) { can_read_pod_logs? } do |environment|
environment.elastic_stack_available?
end
private
alias_method :environment, :object
......@@ -63,6 +79,10 @@ class EnvironmentEntity < Grape::Entity
can?(current_user, :update_environment, environment)
end
def can_read_pod_logs?
can?(current_user, :read_pod_logs, environment.project)
end
def cluster_platform_kubernetes?
deployment_platform && deployment_platform.is_a?(Clusters::Platforms::Kubernetes)
end
......
......@@ -263,7 +263,11 @@
%span
= _('Serverless')
= render_if_exists 'layouts/nav/sidebar/pod_logs_link' # EE-specific
- if project_nav_tab?(:environments) && can?(current_user, :read_pod_logs, @project)
= nav_link(controller: :logs, action: [:index]) do
= link_to project_logs_path(@project), title: _('Logs') do
%span
= _('Logs')
- if project_nav_tab? :clusters
- show_cluster_hint = show_gke_cluster_integration_callout?(@project)
......
---
title: Move pod logs to core
merge_request: 25455
author:
type: changed
......@@ -175,6 +175,13 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
resources :logs, only: [:index] do
collection do
get :k8s
get :elasticsearch
end
end
resources :starrers, only: [:index]
resources :forks, only: [:index, :new, :create]
resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ }
......
......@@ -88,12 +88,13 @@ dropdown box above the upper right corner of the panel:
The options are:
- [View logs](#view-logs-ultimate) **(ULTIMATE)**
- [View logs](#view-logs)
- [Download CSV](#download-csv)
##### View logs **(ULTIMATE)**
##### View logs
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/201846) in GitLab Ultimate 12.8.
> [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) to [GitLab Core](https://about.gitlab.com/pricing/) 12.9.
This can be useful if you are triaging an application incident and need to
[explore logs](../project/integrations/prometheus.md#view-logs-ultimate)
......
......@@ -27,7 +27,7 @@ Using the GitLab project Kubernetes integration, you can:
- Use [Web terminals](#web-terminals).
- Use [Deploy Boards](#deploy-boards-premium). **(PREMIUM)**
- Use [Canary Deployments](#canary-deployments-premium). **(PREMIUM)**
- View [Logs](#logs-ultimate). **(ULTIMATE)**
- View [Logs](#logs).
- Run serverless workloads on [Kubernetes with Knative](serverless/index.md).
### Deploy Boards **(PREMIUM)**
......@@ -48,7 +48,7 @@ the need to leave GitLab.
[Read more about Canary Deployments](../canary_deployments.md)
### Logs **(ULTIMATE)**
### Logs
GitLab makes it easy to view the logs of running pods in connected Kubernetes clusters. By displaying the logs directly in GitLab, developers can avoid having to manage console tools or jump to a different interface.
......
# Kubernetes Logs **(ULTIMATE)**
# Kubernetes Logs
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/4752) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
> [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) to [GitLab Core](https://about.gitlab.com/pricing/) 12.9.
GitLab makes it easy to view the logs of running pods in [connected Kubernetes clusters](index.md).
By displaying the logs directly in GitLab, developers can avoid having to manage console tools or jump to a different interface.
......
......@@ -90,41 +90,6 @@ export default {
return axios.delete(url);
},
/**
* Returns pods logs for an environment with an optional pod and container
*
* @param {Object} params
* @param {Object} param.environment - Environment object
* @param {string=} params.podName - Pod name, if not set the backend assumes a default one
* @param {string=} params.containerName - Container name, if not set the backend assumes a default one
* @param {string=} params.start - Starting date to query the logs in ISO format
* @param {string=} params.end - Ending date to query the logs in ISO format
* @returns {Promise} Axios promise for the result of a GET request of logs
*/
getPodLogs({ environment, podName, containerName, search, start, end }) {
const url = this.buildUrl(environment.logs_api_path);
const params = {};
if (podName) {
params.pod_name = podName;
}
if (containerName) {
params.container_name = containerName;
}
if (search) {
params.search = search;
}
if (start) {
params.start = start;
}
if (end) {
params.end = end;
}
return axios.get(url, { params });
},
groupPackages(id, options = {}) {
const url = Api.buildUrl(this.groupPackagesPath).replace(':id', id);
return axios.get(url, options);
......
.build-page-pod-logs {
.build-trace-container {
position: relative;
}
.build-trace {
@include build-trace();
}
.top-bar {
@include build-trace-top-bar($gl-line-height * 5);
.dropdown-menu-toggle {
width: 200px;
@include media-breakpoint-up(sm) {
width: 300px;
}
}
.controllers {
@include build-controllers(16px, flex-end, true, 2);
}
.refresh-control {
@include build-controllers(16px, flex-end, true, 0);
margin-left: 2px;
}
}
.btn-refresh svg {
top: 0;
}
.build-loader-animation {
@include build-loader-animation;
}
}
......@@ -30,15 +30,6 @@ module EE
project.feature_available?(:custom_prometheus_metrics) && can?(current_user, :admin_project, project)
end
def environment_logs_data(project, environment)
{
"environment-name": environment.name,
"environments-path": project_environments_path(project, format: :json),
"environment-id": environment.id,
"cluster-applications-documentation-path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack')
}
end
def metrics_data(project, environment)
ee_metrics_data = {
"custom-metrics-path" => project_prometheus_metrics_path(project),
......
......@@ -77,10 +77,6 @@ module EE
result || ::Gitlab::Kubernetes::RolloutStatus.loading
end
def elastic_stack_available?
!!deployment_platform&.cluster&.application_elastic_stack&.available?
end
private
def rollout_status_available?
......
......@@ -121,7 +121,6 @@ class License < ApplicationRecord
license_management
license_scanning
personal_access_token_expiration_policy
pod_logs
prometheus_alerts
pseudonymizer
report_approver_rules
......
......@@ -85,11 +85,6 @@ module EE
@subject.feature_available?(:reject_unsigned_commits)
end
with_scope :subject
condition(:pod_logs_enabled) do
@subject.feature_available?(:pod_logs, @user)
end
with_scope :subject
condition(:security_dashboard_enabled) do
@subject.feature_available?(:security_dashboard)
......@@ -238,7 +233,6 @@ module EE
rule { license_scanning_enabled & can?(:maintainer_access) }.enable :admin_software_license_policy
rule { pod_logs_enabled & can?(:maintainer_access) }.enable :read_pod_logs
rule { prometheus_alerts_enabled & can?(:maintainer_access) }.enable :read_prometheus_alerts
rule { auditor }.policy do
......
......@@ -7,30 +7,10 @@ module EE
prepended do
expose :rollout_status, if: -> (*) { can_read_deploy_board? }, using: ::RolloutStatusEntity
expose :logs_path, if: -> (*) { can_read_pod_logs? } do |environment|
project_logs_path(environment.project, environment_name: environment.name)
end
expose :logs_api_path, if: -> (*) { can_read_pod_logs? } do |environment|
if environment.elastic_stack_available?
elasticsearch_project_logs_path(environment.project, environment_name: environment.name, format: :json)
else
k8s_project_logs_path(environment.project, environment_name: environment.name, format: :json)
end
end
expose :enable_advanced_logs_querying, if: -> (*) { can_read_pod_logs? } do |environment|
environment.elastic_stack_available?
end
end
private
def can_read_pod_logs?
can?(current_user, :read_pod_logs, environment.project)
end
def can_read_deploy_board?
can?(current_user, :read_deploy_board, environment.project)
end
......
- return unless can?(current_user, :read_pod_logs, @project)
- return unless project_nav_tab?(:environments)
= nav_link(controller: :logs, action: [:index]) do
= link_to project_logs_path(@project), title: _('Logs') do
%span
= _('Logs')
......@@ -73,13 +73,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resource :threat_monitoring, only: [:show], controller: :threat_monitoring
resources :logs, only: [:index] do
collection do
get :k8s
get :elasticsearch
end
end
resources :protected_environments, only: [:create, :update, :destroy], constraints: { id: /\d+/ } do
collection do
get 'search'
......
......@@ -14,8 +14,6 @@ describe 'Environment > Pod Logs', :js do
let(:service) { create(:cluster_platform_kubernetes, :configured) }
before do
stub_licensed_features(pod_logs: true)
create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project])
create(:deployment, :success, environment: environment)
......
......@@ -24,6 +24,7 @@
{ "$ref": "../rollout_status.json" }
]
},
"logs_path": { "type": "string" },
"updated_at": { "type": "date" }
},
"additionalProperties": false
......
......@@ -57,6 +57,15 @@
"folder_path": {
"type": "string"
},
"logs_path": {
"type": "string"
},
"logs_api_path": {
"type": "string"
},
"enable_advanced_logs_querying": {
"type": "boolean"
},
"created_at": {
"type": "date"
},
......
......@@ -229,39 +229,4 @@ describe Environment, :use_clean_rails_memory_store_caching do
end
end
end
describe '#elastic_stack_available?' do
let!(:cluster) { create(:cluster, :project, :provided_by_user, projects: [project]) }
let!(:deployment) { create(:deployment, :success, environment: environment, project: project) }
context 'when app does not exist' do
it 'returns false' do
expect(environment.elastic_stack_available?).to be(false)
end
end
context 'when app exists' do
let!(:application) { create(:clusters_applications_elastic_stack, cluster: cluster) }
it 'returns false' do
expect(environment.elastic_stack_available?).to be(false)
end
end
context 'when app is installed' do
let!(:application) { create(:clusters_applications_elastic_stack, :installed, cluster: cluster) }
it 'returns true' do
expect(environment.elastic_stack_available?).to be(true)
end
end
context 'when app is updated' do
let!(:application) { create(:clusters_applications_elastic_stack, :updated, cluster: cluster) }
it 'returns true' do
expect(environment.elastic_stack_available?).to be(true)
end
end
end
end
......@@ -26,12 +26,16 @@ describe Groups::ClustersController do
it 'avoids N+1 database queries' do
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { go }.count
deployment_count = 2
create_list(:deployment, 2, :success, cluster: cluster)
create_list(:deployment, deployment_count, :success, cluster: cluster)
# TODO remove this leeway when we refactor away from deployment_platform
# (https://gitlab.com/gitlab-org/gitlab/issues/13635)
leeway = 5
leeway = deployment_count * 2
# it also appears that `can_read_pod_logs?` in ee/app/serializers/clusters/environment_entity.rb
# generates 3 additional queries per deployment
leeway += deployment_count * 3
expect { go }.not_to exceed_all_query_limit(control_count + leeway)
end
end
......
......@@ -51,21 +51,8 @@ describe Clusters::EnvironmentEntity do
end
end
context 'when pod_logs are available' do
before do
stub_licensed_features(pod_logs: true)
project.add_maintainer(user)
end
it 'exposes logs_path' do
expect(subject).to include(:logs_path)
end
end
context 'when pod_logs are not available' do
it 'does not expose logs_path' do
expect(subject).not_to include(:logs_path)
end
it 'exposes logs_path' do
expect(subject).to include(:logs_path)
end
end
end
......@@ -4,7 +4,6 @@ require 'spec_helper'
describe EnvironmentEntity do
include KubernetesHelpers
include Gitlab::Routing.url_helpers
let(:user) { create(:user) }
let(:environment) { create(:environment) }
......@@ -46,39 +45,5 @@ describe EnvironmentEntity do
expect(subject).not_to include(:rollout_status)
end
end
context 'when pod_logs are available' do
before do
stub_licensed_features(pod_logs: true)
end
it 'exposes logs keys' do
expect(subject).to include(:logs_path)
expect(subject).to include(:logs_api_path)
expect(subject).to include(:enable_advanced_logs_querying)
end
it 'uses k8s api when ES is not available' do
expect(subject[:logs_api_path]).to eq(k8s_project_logs_path(environment.project, environment_name: environment.name, format: :json))
end
it 'uses ES api when ES is available' do
allow(environment).to receive(:elastic_stack_available?).and_return(true)
expect(subject[:logs_api_path]).to eq(elasticsearch_project_logs_path(environment.project, environment_name: environment.name, format: :json))
end
end
context 'when pod_logs are not available' do
before do
stub_licensed_features(pod_logs: false)
end
it 'does not expose logs keys' do
expect(subject).not_to include(:logs_path)
expect(subject).not_to include(:logs_api_path)
expect(subject).not_to include(:enable_advanced_logs_querying)
end
end
end
end
......@@ -22,39 +22,21 @@ describe Projects::LogsController do
end
describe 'GET #index' do
context 'when unlicensed' do
before do
stub_licensed_features(pod_logs: false)
end
let(:empty_project) { create(:project) }
it 'renders forbidden' do
get :index, params: environment_params
it 'renders empty logs page if no environment exists' do
empty_project.add_maintainer(user)
get :index, params: { namespace_id: empty_project.namespace, project_id: empty_project }
expect(response).to have_gitlab_http_status(:not_found)
end
expect(response).to be_ok
expect(response).to render_template 'empty_logs'
end
context 'when licensed' do
before do
stub_licensed_features(pod_logs: true)
end
let(:empty_project) { create(:project) }
it 'renders empty logs page if no environment exists' do
empty_project.add_maintainer(user)
get :index, params: { namespace_id: empty_project.namespace, project_id: empty_project }
expect(response).to be_ok
expect(response).to render_template 'empty_logs'
end
it 'renders index template' do
get :index, params: environment_params
it 'renders index template' do
get :index, params: environment_params
expect(response).to be_ok
expect(response).to render_template 'index'
end
expect(response).to be_ok
expect(response).to render_template 'index'
end
end
......@@ -73,21 +55,11 @@ describe Projects::LogsController do
let_it_be(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project]) }
before do
stub_licensed_features(pod_logs: true)
allow_next_instance_of(service) do |instance|
allow(instance).to receive(:execute).and_return(service_result)
end
end
it 'returns 404 when unlicensed' do
stub_licensed_features(pod_logs: false)
get endpoint, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns the service result' do
get endpoint, params: environment_params(pod_name: pod_name, format: :json)
......
......@@ -70,6 +70,7 @@ describe 'Project navbar' do
_('Environments'),
_('Error Tracking'),
_('Serverless'),
_('Logs'),
_('Kubernetes')
]
},
......
......@@ -26,6 +26,9 @@
"stop_path": { "type": "string" },
"cancel_auto_stop_path": { "type": "string" },
"folder_path": { "type": "string" },
"logs_path": { "type": "string" },
"logs_api_path": { "type": "string" },
"enable_advanced_logs_querying": { "type": "boolean" },
"created_at": { "type": "string", "format": "date-time" },
"updated_at": { "type": "string", "format": "date-time" },
"auto_stop_at": { "type": "string", "format": "date-time" },
......
......@@ -2,9 +2,9 @@ import Vue from 'vue';
import { GlDropdown, GlDropdownItem, GlSearchBoxByClick } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import EnvironmentLogs from 'ee/logs/components/environment_logs.vue';
import EnvironmentLogs from '~/logs/components/environment_logs.vue';
import { createStore } from 'ee/logs/stores';
import { createStore } from '~/logs/stores';
import { scrollDown } from '~/lib/utils/scroll_utils';
import {
mockEnvName,
......
import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
import LogControlButtons from 'ee/logs/components/log_control_buttons.vue';
import LogControlButtons from '~/logs/components/log_control_buttons.vue';
import {
canScroll,
isScrolledToTop,
......
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as types from 'ee/logs/stores/mutation_types';
import * as types from '~/logs/stores/mutation_types';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
import logsPageState from 'ee/logs/stores/state';
import logsPageState from '~/logs/stores/state';
import {
setInitData,
setSearch,
showPodLogs,
fetchEnvironments,
fetchLogs,
} from 'ee/logs/stores/actions';
} from '~/logs/stores/actions';
import { defaultTimeRange } from '~/monitoring/constants';
......@@ -30,7 +30,7 @@ import {
jest.mock('~/flash');
jest.mock('~/lib/utils/datetime_range');
jest.mock('ee/logs/utils');
jest.mock('~/logs/utils');
const mockDefaultRange = {
start: '2020-01-10T18:00:00.000Z',
......
import * as getters from 'ee/logs/stores/getters';
import logsPageState from 'ee/logs/stores/state';
import * as getters from '~/logs/stores/getters';
import logsPageState from '~/logs/stores/state';
import { mockLogsResult, mockTrace } from '../mock_data';
......
import mutations from 'ee/logs/stores/mutations';
import * as types from 'ee/logs/stores/mutation_types';
import mutations from '~/logs/stores/mutations';
import * as types from '~/logs/stores/mutation_types';
import logsPageState from 'ee/logs/stores/state';
import logsPageState from '~/logs/stores/state';
import {
mockEnvName,
mockEnvironments,
......
import { getTimeRange } from 'ee/logs/utils';
import { getTimeRange } from '~/logs/utils';
describe('logs/utils', () => {
describe('getTimeRange', () => {
......
......@@ -10,7 +10,7 @@ describe Gitlab::Elasticsearch::Logs do
let(:es_message_3) { { timestamp: "2019-12-13T14:35:36.034Z", message: "10.8.2.1 - - [04/Nov/2019:23:09:24 UTC] \"GET / HTTP/1.1\" 200 13" } }
let(:es_message_4) { { timestamp: "2019-12-13T14:35:37.034Z", message: "- -\u003e /" } }
let(:es_response) { JSON.parse(fixture_file('lib/elasticsearch/logs_response.json', dir: 'ee')) }
let(:es_response) { JSON.parse(fixture_file('lib/elasticsearch/logs_response.json')) }
subject { described_class.new(client) }
......@@ -21,12 +21,12 @@ describe Gitlab::Elasticsearch::Logs do
let(:start_time) { "2019-12-13T14:35:34.034Z" }
let(:end_time) { "2019-12-13T14:35:34.034Z" }
let(:body) { JSON.parse(fixture_file('lib/elasticsearch/query.json', dir: 'ee')) }
let(:body_with_container) { JSON.parse(fixture_file('lib/elasticsearch/query_with_container.json', dir: 'ee')) }
let(:body_with_search) { JSON.parse(fixture_file('lib/elasticsearch/query_with_search.json', dir: 'ee')) }
let(:body_with_times) { JSON.parse(fixture_file('lib/elasticsearch/query_with_times.json', dir: 'ee')) }
let(:body_with_start_time) { JSON.parse(fixture_file('lib/elasticsearch/query_with_start_time.json', dir: 'ee')) }
let(:body_with_end_time) { JSON.parse(fixture_file('lib/elasticsearch/query_with_end_time.json', dir: 'ee')) }
let(:body) { JSON.parse(fixture_file('lib/elasticsearch/query.json')) }
let(:body_with_container) { JSON.parse(fixture_file('lib/elasticsearch/query_with_container.json')) }
let(:body_with_search) { JSON.parse(fixture_file('lib/elasticsearch/query_with_search.json')) }
let(:body_with_times) { JSON.parse(fixture_file('lib/elasticsearch/query_with_times.json')) }
let(:body_with_start_time) { JSON.parse(fixture_file('lib/elasticsearch/query_with_start_time.json')) }
let(:body_with_end_time) { JSON.parse(fixture_file('lib/elasticsearch/query_with_end_time.json')) }
RSpec::Matchers.define :a_hash_equal_to_json do |expected|
match do |actual|
......
......@@ -1266,4 +1266,39 @@ describe Environment, :use_clean_rails_memory_store_caching do
expect(env).to be_persisted
end
end
describe '#elastic_stack_available?' do
let!(:cluster) { create(:cluster, :project, :provided_by_user, projects: [project]) }
let!(:deployment) { create(:deployment, :success, environment: environment, project: project, cluster: cluster) }
context 'when app does not exist' do
it 'returns false' do
expect(environment.elastic_stack_available?).to be(false)
end
end
context 'when app exists' do
let!(:application) { create(:clusters_applications_elastic_stack, cluster: cluster) }
it 'returns false' do
expect(environment.elastic_stack_available?).to be(false)
end
end
context 'when app is installed' do
let!(:application) { create(:clusters_applications_elastic_stack, :installed, cluster: cluster) }
it 'returns true' do
expect(environment.elastic_stack_available?).to be(true)
end
end
context 'when app is updated' do
let!(:application) { create(:clusters_applications_elastic_stack, :updated, cluster: cluster) }
it 'returns true' do
expect(environment.elastic_stack_available?).to be(true)
end
end
end
end
......@@ -3,6 +3,8 @@
require 'spec_helper'
describe EnvironmentEntity do
include Gitlab::Routing.url_helpers
let(:request) { double('request') }
let(:entity) do
described_class.new(environment, request: spy('request'))
......@@ -71,4 +73,22 @@ describe EnvironmentEntity do
expect(subject).to include(:cancel_auto_stop_path, :auto_stop_at)
end
end
context 'pod_logs' do
it 'exposes logs keys' do
expect(subject).to include(:logs_path)
expect(subject).to include(:logs_api_path)
expect(subject).to include(:enable_advanced_logs_querying)
end
it 'uses k8s api when ES is not available' do
expect(subject[:logs_api_path]).to eq(k8s_project_logs_path(environment.project, environment_name: environment.name, format: :json))
end
it 'uses ES api when ES is available' do
allow(environment).to receive(:elastic_stack_available?).and_return(true)
expect(subject[:logs_api_path]).to eq(elasticsearch_project_logs_path(environment.project, environment_name: environment.name, format: :json))
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment