Commit 46ad3339 authored by Adrien Kohlbecker's avatar Adrien Kohlbecker Committed by Kamil Trzciński

Rework logs navigation scheme

Create a single logs route and API in preparation for more search
capabilities
parent 06be63d0
...@@ -145,7 +145,8 @@ export default { ...@@ -145,7 +145,8 @@ export default {
:is-loading="model.isLoadingDeployBoard" :is-loading="model.isLoadingDeployBoard"
:is-empty="model.isEmptyDeployBoard" :is-empty="model.isEmptyDeployBoard"
:has-legacy-app-label="model.hasLegacyAppLabel" :has-legacy-app-label="model.hasLegacyAppLabel"
:logs-path="model.logs_path" :project-path="model.project_path"
:environment-name="model.name"
/> />
</div> </div>
</div> </div>
......
---
title: Rework pod logs navigation scheme
merge_request: 20578
author:
type: changed
...@@ -11,11 +11,7 @@ export default { ...@@ -11,11 +11,7 @@ export default {
groupEpicsPath: groupEpicsPath:
'/api/:version/groups/:id/epics?include_ancestor_groups=:includeAncestorGroups&include_descendant_groups=:includeDescendantGroups', '/api/:version/groups/:id/epics?include_ancestor_groups=:includeAncestorGroups&include_descendant_groups=:includeDescendantGroups',
epicIssuePath: '/api/:version/groups/:id/epics/:epic_iid/issues/:issue_id', epicIssuePath: '/api/:version/groups/:id/epics/:epic_iid/issues/:issue_id',
podLogsPath: '/:project_full_path/-/environments/:environment_id/pods/containers/logs.json', podLogsPath: '/:project_full_path/-/logs/k8s.json',
podLogsPathWithPod:
'/:project_full_path/-/environments/:environment_id/pods/:pod_name/containers/logs.json',
podLogsPathWithPodContainer:
'/:project_full_path/-/environments/:environment_id/pods/:pod_name/containers/:container_name/logs.json',
groupPackagesPath: '/api/:version/groups/:id/packages', groupPackagesPath: '/api/:version/groups/:id/packages',
projectPackagesPath: '/api/:version/projects/:id/packages', projectPackagesPath: '/api/:version/projects/:id/packages',
projectPackagePath: '/api/:version/projects/:id/packages/:package_id', projectPackagePath: '/api/:version/projects/:id/packages/:package_id',
...@@ -96,25 +92,21 @@ export default { ...@@ -96,25 +92,21 @@ export default {
* @param {string=} params.containerName - Container 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
* @returns {Promise} Axios promise for the result of a GET request of logs * @returns {Promise} Axios promise for the result of a GET request of logs
*/ */
getPodLogs({ projectPath, environmentId, podName, containerName }) { getPodLogs({ projectPath, environmentName, podName, containerName }) {
let logPath = this.podLogsPath; const url = this.buildUrl(this.podLogsPath).replace(':project_full_path', projectPath);
if (podName && containerName) {
logPath = this.podLogsPathWithPodContainer;
} else if (podName) {
logPath = this.podLogsPathWithPod;
}
let url = this.buildUrl(logPath) const params = {
.replace(':project_full_path', projectPath) environment_name: environmentName,
.replace(':environment_id', environmentId); };
if (podName) { if (podName) {
url = url.replace(':pod_name', podName); params.pod_name = podName;
} }
if (containerName) { if (containerName) {
url = url.replace(':container_name', containerName); params.container_name = containerName;
} }
return axios.get(url);
return axios.get(url, { params });
}, },
groupPackages(id, options = {}) { groupPackages(id, options = {}) {
......
...@@ -143,7 +143,8 @@ export default { ...@@ -143,7 +143,8 @@ export default {
:tooltip-text="instance.tooltip" :tooltip-text="instance.tooltip"
:pod-name="instance.pod_name" :pod-name="instance.pod_name"
:stable="instance.stable" :stable="instance.stable"
:logs-path="`${row.item.environmentPath}/logs`" :project-path="`/${row.item.project.path_with_namespace}`"
:environment-name="row.item.name"
/> />
</template> </template>
</div> </div>
......
...@@ -42,10 +42,13 @@ export default { ...@@ -42,10 +42,13 @@ export default {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
logsPath: { environmentName: {
type: String, type: String,
required: false, required: true,
default: '', },
projectPath: {
type: String,
required: true,
}, },
hasLegacyAppLabel: { hasLegacyAppLabel: {
type: Boolean, type: Boolean,
...@@ -140,8 +143,9 @@ export default { ...@@ -140,8 +143,9 @@ export default {
:key="i" :key="i"
:status="instance.status" :status="instance.status"
:tooltip-text="instance.tooltip" :tooltip-text="instance.tooltip"
:environment-name="environmentName"
:pod-name="instance.pod_name" :pod-name="instance.pod_name"
:logs-path="logsPath" :project-path="projectPath"
:stable="instance.stable" :stable="instance.stable"
/> />
</template> </template>
......
...@@ -12,15 +12,11 @@ export default { ...@@ -12,15 +12,11 @@ export default {
LogControlButtons, LogControlButtons,
}, },
props: { props: {
environmentId: {
type: String,
required: true,
},
projectFullPath: { projectFullPath: {
type: String, type: String,
required: true, required: true,
}, },
currentEnvironmentName: { environmentName: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
...@@ -56,14 +52,19 @@ export default { ...@@ -56,14 +52,19 @@ export default {
mounted() { mounted() {
this.setInitData({ this.setInitData({
projectPath: this.projectFullPath, projectPath: this.projectFullPath,
environmentId: this.environmentId, environmentName: this.environmentName,
podName: this.currentPodName, podName: this.currentPodName,
}); });
this.fetchEnvironments(this.environmentsPath); this.fetchEnvironments(this.environmentsPath);
}, },
methods: { methods: {
...mapActions('environmentLogs', ['setInitData', 'showPodLogs', 'fetchEnvironments']), ...mapActions('environmentLogs', [
'setInitData',
'showPodLogs',
'showEnvironment',
'fetchEnvironments',
]),
}, },
}; };
</script> </script>
...@@ -80,7 +81,7 @@ export default { ...@@ -80,7 +81,7 @@ export default {
> >
<gl-dropdown <gl-dropdown
id="environments-dropdown" id="environments-dropdown"
:text="currentEnvironmentName" :text="environments.current"
:disabled="environments.isLoading" :disabled="environments.isLoading"
class="d-flex js-environments-dropdown" class="d-flex js-environments-dropdown"
toggle-class="dropdown-menu-toggle" toggle-class="dropdown-menu-toggle"
...@@ -88,7 +89,7 @@ export default { ...@@ -88,7 +89,7 @@ export default {
<gl-dropdown-item <gl-dropdown-item
v-for="env in environments.options" v-for="env in environments.options"
:key="env.id" :key="env.id"
:href="env.logs_path" @click="showEnvironment(env.name)"
> >
{{ env.name }} {{ env.name }}
</gl-dropdown-item> </gl-dropdown-item>
......
...@@ -6,9 +6,9 @@ import flash from '~/flash'; ...@@ -6,9 +6,9 @@ import flash from '~/flash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import * as types from './mutation_types'; import * as types from './mutation_types';
const requestLogsUntilData = ({ projectPath, environmentId, podName }) => const requestLogsUntilData = ({ projectPath, environmentName, podName }) =>
backOff((next, stop) => { backOff((next, stop) => {
Api.getPodLogs({ projectPath, environmentId, podName }) Api.getPodLogs({ projectPath, environmentName, podName })
.then(res => { .then(res => {
if (res.status === httpStatusCodes.ACCEPTED) { if (res.status === httpStatusCodes.ACCEPTED) {
next(); next();
...@@ -21,8 +21,9 @@ const requestLogsUntilData = ({ projectPath, environmentId, podName }) => ...@@ -21,8 +21,9 @@ const requestLogsUntilData = ({ projectPath, environmentId, podName }) =>
}); });
}); });
export const setInitData = ({ dispatch, commit }, { projectPath, environmentId, podName }) => { export const setInitData = ({ dispatch, commit }, { projectPath, environmentName, podName }) => {
commit(types.SET_PROJECT_ENVIRONMENT, { projectPath, environmentId }); commit(types.SET_PROJECT_PATH, projectPath);
commit(types.SET_PROJECT_ENVIRONMENT, environmentName);
commit(types.SET_CURRENT_POD_NAME, podName); commit(types.SET_CURRENT_POD_NAME, podName);
dispatch('fetchLogs'); dispatch('fetchLogs');
}; };
...@@ -32,6 +33,12 @@ export const showPodLogs = ({ dispatch, commit }, podName) => { ...@@ -32,6 +33,12 @@ export const showPodLogs = ({ dispatch, commit }, podName) => {
dispatch('fetchLogs'); dispatch('fetchLogs');
}; };
export const showEnvironment = ({ dispatch, commit }, environmentName) => {
commit(types.SET_PROJECT_ENVIRONMENT, environmentName);
commit(types.SET_CURRENT_POD_NAME, null);
dispatch('fetchLogs');
};
export const fetchEnvironments = ({ commit }, environmentsPath) => { export const fetchEnvironments = ({ commit }, environmentsPath) => {
commit(types.REQUEST_ENVIRONMENTS_DATA); commit(types.REQUEST_ENVIRONMENTS_DATA);
...@@ -49,7 +56,7 @@ export const fetchEnvironments = ({ commit }, environmentsPath) => { ...@@ -49,7 +56,7 @@ export const fetchEnvironments = ({ commit }, environmentsPath) => {
export const fetchLogs = ({ commit, state }) => { export const fetchLogs = ({ commit, state }) => {
const params = { const params = {
projectPath: state.projectPath, projectPath: state.projectPath,
environmentId: state.environments.current, environmentName: state.environments.current,
podName: state.pods.current, podName: state.pods.current,
}; };
......
export const SET_PROJECT_PATH = 'SET_PROJECT_PATH';
export const SET_PROJECT_ENVIRONMENT = 'SET_PROJECT_ENVIRONMENT'; export const SET_PROJECT_ENVIRONMENT = 'SET_PROJECT_ENVIRONMENT';
export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA'; export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA';
......
...@@ -2,12 +2,14 @@ import * as types from './mutation_types'; ...@@ -2,12 +2,14 @@ import * as types from './mutation_types';
export default { export default {
/** Project data */ /** Project data */
[types.SET_PROJECT_ENVIRONMENT](state, { projectPath, environmentId }) { [types.SET_PROJECT_PATH](state, projectPath) {
state.projectPath = projectPath; state.projectPath = projectPath;
state.environments.current = environmentId;
}, },
/** Environments data */ /** Environments data */
[types.SET_PROJECT_ENVIRONMENT](state, environmentName) {
state.environments.current = environmentName;
},
[types.REQUEST_ENVIRONMENTS_DATA](state) { [types.REQUEST_ENVIRONMENTS_DATA](state) {
state.environments.options = []; state.environments.options = [];
state.environments.isLoading = true; state.environments.isLoading = true;
......
...@@ -47,13 +47,19 @@ export default { ...@@ -47,13 +47,19 @@ export default {
default: true, default: true,
}, },
environmentName: {
type: String,
required: false,
default: '',
},
podName: { podName: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
}, },
logsPath: { projectPath: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
...@@ -74,7 +80,9 @@ export default { ...@@ -74,7 +80,9 @@ export default {
}, },
computedLogPath() { computedLogPath() {
return this.isLink ? `${this.logsPath}?pod_name=${this.podName}` : null; return this.isLink
? `${this.projectPath}/-/logs?environment_name=${this.environmentName}&pod_name=${this.podName}`
: null;
}, },
}, },
}; };
......
...@@ -6,49 +6,11 @@ module EE ...@@ -6,49 +6,11 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
prepended do prepended do
before_action :authorize_read_pod_logs!, only: [:k8s_pod_logs, :logs]
before_action :environment_ee, only: [:k8s_pod_logs, :logs]
before_action :authorize_create_environment_terminal!, only: [:terminal] before_action :authorize_create_environment_terminal!, only: [:terminal]
end end
def logs_redirect
environment = project.default_environment
if environment
redirect_to logs_project_environment_path(project, environment)
else
render :empty_logs
end
end
def logs
end
def k8s_pod_logs
respond_to do |format|
format.json do
::Gitlab::UsageCounters::PodLogs.increment(project.id)
::Gitlab::PollingInterval.set_header(response, interval: 3_000)
result = PodLogsService.new(environment, params: params.permit!).execute
if result[:status] == :processing
head :accepted
elsif result[:status] == :success
render json: result
else
render status: :bad_request, json: result
end
end
end
end
private private
def environment_ee
environment
end
def authorize_create_environment_terminal! def authorize_create_environment_terminal!
return render_404 unless can?(current_user, :create_environment_terminal, environment) return render_404 unless can?(current_user, :create_environment_terminal, environment)
end end
......
# frozen_string_literal: true
module Projects
class LogsController < Projects::ApplicationController
before_action :authorize_read_pod_logs!
before_action :environment
before_action do
push_frontend_feature_flag(:environment_logs_use_vue_ui)
end
def index
if environment.nil?
render :empty_logs
else
render :index
end
end
def k8s
::Gitlab::UsageCounters::PodLogs.increment(project.id)
::Gitlab::PollingInterval.set_header(response, interval: 3_000)
result = PodLogsService.new(environment, params: filter_params).execute
if result[:status] == :processing
head :accepted
elsif result[:status] == :success
render json: result
else
render status: :bad_request, json: result
end
end
private
def index_params
params.permit(:environment_name)
end
def filter_params
params.permit(:container_name, :pod_name)
end
def environment
@environment ||= if index_params.key?(:environment_name)
EnvironmentsFinder.new(project, current_user, name: index_params[:environment_name]).find.first
else
project.default_environment
end
end
end
end
...@@ -32,7 +32,7 @@ module EE ...@@ -32,7 +32,7 @@ module EE
def environment_logs_data(project, environment) def environment_logs_data(project, environment)
{ {
"current-environment-name": environment.name, "environment-name": environment.name,
"environments-path": project_environments_path(project, format: :json), "environments-path": project_environments_path(project, format: :json),
"project-full-path": project.full_path, "project-full-path": project.full_path,
"environment-id": environment.id "environment-id": environment.id
......
...@@ -68,11 +68,11 @@ module EE ...@@ -68,11 +68,11 @@ module EE
::Gitlab::EtagCaching::Store.new.tap do |store| ::Gitlab::EtagCaching::Store.new.tap do |store|
store.touch( store.touch(
::Gitlab::Routing.url_helpers.k8s_pod_logs_project_environment_path( ::Gitlab::Routing.url_helpers.k8s_project_logs_path(
environment.project, environment.project,
environment, environment_name: environment.name,
opts['pod_name'], pod_name: opts['pod_name'],
opts['container_name'], container_name: opts['container_name'],
format: :json format: :json
) )
) )
......
...@@ -8,17 +8,13 @@ module EE ...@@ -8,17 +8,13 @@ module EE
prepended do prepended do
expose :rollout_status, if: -> (*) { can_read_deploy_board? }, using: ::RolloutStatusEntity expose :rollout_status, if: -> (*) { can_read_deploy_board? }, using: ::RolloutStatusEntity
expose :logs_path, if: -> (*) { can_read_pod_logs? } do |environment| expose :project_path do |environment|
logs_project_environment_path(environment.project, environment) project_path(environment.project)
end end
end end
private private
def can_read_pod_logs?
can?(current_user, :read_pod_logs, environment.project)
end
def can_read_deploy_board? def can_read_deploy_board?
can?(current_user, :read_deploy_board, environment.project) can?(current_user, :read_deploy_board, environment.project)
end end
......
- return unless can?(current_user, :read_pod_logs, @project) - return unless can?(current_user, :read_pod_logs, @project)
- return unless project_nav_tab?(:environments) - return unless project_nav_tab?(:environments)
= nav_link(controller: :environments, action: [:logs, :logs_redirect]) do = nav_link(controller: :logs, action: [:show]) do
= link_to logs_project_environments_path(@project), title: _('Pod logs') do = link_to project_logs_path(@project), title: _('Pod logs') do
%span %span
= _('Pod logs') = _('Pod logs')
...@@ -70,14 +70,9 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -70,14 +70,9 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :licenses, only: [:index, :create, :update] resources :licenses, only: [:index, :create, :update]
end end
resources :environments, only: [] do resources :logs, only: [:index] do
member do
get :logs
get '/pods/(:pod_name)/containers/(:container_name)/logs', to: 'environments#k8s_pod_logs', as: :k8s_pod_logs
end
collection do collection do
get :logs, action: :logs_redirect get :k8s
end end
end end
......
...@@ -10,7 +10,7 @@ module EE ...@@ -10,7 +10,7 @@ module EE
'epic_notes' 'epic_notes'
), ),
::Gitlab::EtagCaching::Router::Route.new( ::Gitlab::EtagCaching::Router::Route.new(
%r(#{::Gitlab::EtagCaching::Router::RESERVED_WORDS_PREFIX}/environments/\d+/pods/(\S+/)?containers/(\S+/)?logs\.json\z), %r(#{::Gitlab::EtagCaching::Router::RESERVED_WORDS_PREFIX}/logs/k8s\.json(\?.*)?\z),
'k8s_pod_logs' 'k8s_pod_logs'
) )
].freeze ].freeze
......
...@@ -76,169 +76,6 @@ describe Projects::EnvironmentsController do ...@@ -76,169 +76,6 @@ describe Projects::EnvironmentsController do
end end
end end
describe 'GET #logs_redirect' do
let(:project) { create(:project) }
it 'redirects to environment if it exists' do
environment = create(:environment, name: 'production', project: project)
get :logs_redirect, params: { namespace_id: project.namespace, project_id: project }
expect(response).to redirect_to(logs_project_environment_path(project, environment))
end
it 'renders empty logs page if no environment exists' do
get :logs_redirect, params: { namespace_id: project.namespace, project_id: project }
expect(response).to be_ok
expect(response).to render_template 'empty_logs'
end
end
describe 'GET logs' do
let(:pod_name) { "foo" }
before do
stub_licensed_features(pod_logs: true)
end
context 'when unlicensed' do
before do
stub_licensed_features(pod_logs: false)
end
it 'renders forbidden' do
get :logs, params: environment_params(pod_name: pod_name)
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'when licensed' do
it 'renders logs template' do
get :logs, params: environment_params(pod_name: pod_name)
expect(response).to be_ok
expect(response).to render_template 'logs'
end
end
end
describe 'GET k8s_pod_logs' do
let(:pod_name) { "foo" }
let(:container) { 'container-1' }
let(:service_result) do
{
status: :success,
logs: ['Log 1', 'Log 2', 'Log 3'],
message: 'message',
pods: [pod_name],
pod_name: pod_name,
container_name: container
}
end
before do
stub_licensed_features(pod_logs: true)
allow_any_instance_of(PodLogsService).to receive(:execute).and_return(service_result)
end
shared_examples 'resource not found' do |message|
it 'returns 400', :aggregate_failures do
get :k8s_pod_logs, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq(message)
expect(json_response['pods']).to match_array([pod_name])
expect(json_response['pod_name']).to eq(pod_name)
expect(json_response['container_name']).to eq(container)
end
end
it 'returns the logs for a specific pod', :aggregate_failures do
get :k8s_pod_logs, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:success)
expect(json_response["logs"]).to match_array(["Log 1", "Log 2", "Log 3"])
expect(json_response["pods"]).to match_array([pod_name])
expect(json_response['message']).to eq(service_result[:message])
expect(json_response['pod_name']).to eq(pod_name)
expect(json_response['container_name']).to eq(container)
end
it 'registers a usage of the endpoint' do
expect(::Gitlab::UsageCounters::PodLogs).to receive(:increment).with(project.id)
get :k8s_pod_logs, params: environment_params(pod_name: pod_name, format: :json)
end
context 'when kubernetes API returns error' do
let(:service_result) do
{
status: :error,
message: 'Kubernetes API returned status code: 400',
pods: [pod_name],
pod_name: pod_name,
container_name: container
}
end
it 'returns bad request' do
get :k8s_pod_logs, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response["logs"]).to eq(nil)
expect(json_response["pods"]).to match_array([pod_name])
expect(json_response["message"]).to eq('Kubernetes API returned status code: 400')
expect(json_response['pod_name']).to eq(pod_name)
expect(json_response['container_name']).to eq(container)
end
end
context 'when pod does not exist' do
let(:service_result) do
{
status: :error,
message: 'Pod not found',
pods: [pod_name],
pod_name: pod_name,
container_name: container
}
end
it_behaves_like 'resource not found', 'Pod not found'
end
context 'when service returns error without pods, pod_name, container_name' do
let(:service_result) do
{
status: :error,
message: 'No deployment platform'
}
end
it 'returns the error without pods, pod_name and container_name' do
get :k8s_pod_logs, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq('No deployment platform')
expect(json_response.keys).to contain_exactly('message', 'status')
end
end
context 'when service returns status processing' do
let(:service_result) { { status: :processing } }
it 'renders accepted' do
get :k8s_pod_logs, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:accepted)
end
end
end
describe '#GET terminal' do describe '#GET terminal' do
let(:protected_environment) { create(:protected_environment, name: environment.name, project: project) } let(:protected_environment) { create(:protected_environment, name: environment.name, project: project) }
......
# frozen_string_literal: true
require 'spec_helper'
describe Projects::LogsController do
include KubernetesHelpers
set(:user) { create(:user) }
set(:project) { create(:project) }
set(:environment) do
create(:environment, name: 'production', project: project)
end
let(:pod_name) { "foo" }
let(:container) { 'container-1' }
before do
project.add_maintainer(user)
sign_in(user)
end
describe 'GET #index' do
context 'when unlicensed' do
before do
stub_licensed_features(pod_logs: false)
end
it 'renders forbidden' do
get :index, params: environment_params
expect(response).to have_gitlab_http_status(:not_found)
end
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
expect(response).to be_ok
expect(response).to render_template 'index'
end
end
end
describe "GET #k8s" do
let(:service_result) do
{
status: :success,
logs: ['Log 1', 'Log 2', 'Log 3'],
message: 'message',
pods: [pod_name],
pod_name: pod_name,
container_name: container
}
end
before do
stub_licensed_features(pod_logs: true)
allow_any_instance_of(PodLogsService).to receive(:execute).and_return(service_result)
end
shared_examples 'resource not found' do |message|
it 'returns 400', :aggregate_failures do
get :k8s, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq(message)
expect(json_response['pods']).to match_array([pod_name])
expect(json_response['pod_name']).to eq(pod_name)
expect(json_response['container_name']).to eq(container)
end
end
it 'returns the logs for a specific pod', :aggregate_failures do
get :k8s, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:success)
expect(json_response["logs"]).to match_array(["Log 1", "Log 2", "Log 3"])
expect(json_response["pods"]).to match_array([pod_name])
expect(json_response['message']).to eq(service_result[:message])
expect(json_response['pod_name']).to eq(pod_name)
expect(json_response['container_name']).to eq(container)
end
it 'registers a usage of the endpoint' do
expect(::Gitlab::UsageCounters::PodLogs).to receive(:increment).with(project.id)
get :k8s, params: environment_params(pod_name: pod_name, format: :json)
end
context 'when kubernetes API returns error' do
let(:service_result) do
{
status: :error,
message: 'Kubernetes API returned status code: 400',
pods: [pod_name],
pod_name: pod_name,
container_name: container
}
end
it 'returns bad request' do
get :k8s, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response["logs"]).to eq(nil)
expect(json_response["pods"]).to match_array([pod_name])
expect(json_response["message"]).to eq('Kubernetes API returned status code: 400')
expect(json_response['pod_name']).to eq(pod_name)
expect(json_response['container_name']).to eq(container)
end
end
context 'when pod does not exist' do
let(:service_result) do
{
status: :error,
message: 'Pod not found',
pods: [pod_name],
pod_name: pod_name,
container_name: container
}
end
it_behaves_like 'resource not found', 'Pod not found'
end
context 'when service returns error without pods, pod_name, container_name' do
let(:service_result) do
{
status: :error,
message: 'No deployment platform'
}
end
it 'returns the error without pods, pod_name and container_name' do
get :k8s, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq('No deployment platform')
expect(json_response.keys).to contain_exactly('message', 'status')
end
end
context 'when service returns status processing' do
let(:service_result) { { status: :processing } }
it 'renders accepted' do
get :k8s, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:accepted)
end
end
end
def environment_params(opts = {})
opts.reverse_merge(namespace_id: project.namespace,
project_id: project,
environment_name: environment.name)
end
end
...@@ -37,7 +37,7 @@ describe 'Environment > Pod Logs', :js do ...@@ -37,7 +37,7 @@ describe 'Environment > Pod Logs', :js do
it "shows environments in dropdown" do it "shows environments in dropdown" do
create(:environment, project: project) create(:environment, project: project)
visit logs_project_environment_path(environment.project, environment, pod_name: pod_name) visit project_logs_path(environment.project, environment_name: environment.name, pod_name: pod_name)
wait_for_requests wait_for_requests
...@@ -56,7 +56,7 @@ describe 'Environment > Pod Logs', :js do ...@@ -56,7 +56,7 @@ describe 'Environment > Pod Logs', :js do
context 'with logs', :use_clean_rails_memory_store_caching do context 'with logs', :use_clean_rails_memory_store_caching do
it "shows pod logs", :sidekiq_might_not_need_inline do it "shows pod logs", :sidekiq_might_not_need_inline do
visit logs_project_environment_path(environment.project, environment, pod_name: pod_name) visit project_logs_path(environment.project, environment_name: environment.name, pod_name: pod_name)
wait_for_requests wait_for_requests
...@@ -95,7 +95,7 @@ describe 'Environment > Pod Logs', :js do ...@@ -95,7 +95,7 @@ describe 'Environment > Pod Logs', :js do
end end
def load_and_scroll_down def load_and_scroll_down
visit logs_project_environment_path(environment.project, environment, pod_name: pod_name) visit project_logs_path(environment.project, environment_name: environment.name, pod_name: pod_name)
wait_for_requests wait_for_requests
......
...@@ -27,10 +27,7 @@ ...@@ -27,10 +27,7 @@
"type": "string" "type": "string"
}, },
"environment_type": { "environment_type": {
"type": [ "type": ["string", "null"]
"string",
"null"
]
}, },
"last_deployment": { "last_deployment": {
"oneOf": [ "oneOf": [
...@@ -60,7 +57,7 @@ ...@@ -60,7 +57,7 @@
"folder_path": { "folder_path": {
"type": "string" "type": "string"
}, },
"logs_path": { "project_path": {
"type": "string" "type": "string"
}, },
"created_at": { "created_at": {
......
...@@ -166,11 +166,11 @@ describe('Api', () => { ...@@ -166,11 +166,11 @@ describe('Api', () => {
describe('getPodLogs', () => { describe('getPodLogs', () => {
const projectPath = 'root/test-project'; const projectPath = 'root/test-project';
const environmentId = 2; const environmentName = 'production';
const podName = 'pod'; const podName = 'pod';
const containerName = 'container'; const containerName = 'container';
const lastUrl = () => mock.history.get[0].url; const getRequest = () => mock.history.get[0];
beforeEach(() => { beforeEach(() => {
mock.onAny().reply(200); mock.onAny().reply(200);
...@@ -181,33 +181,45 @@ describe('Api', () => { ...@@ -181,33 +181,45 @@ describe('Api', () => {
}); });
it('calls `axios.get` with pod_name and container_name', done => { it('calls `axios.get` with pod_name and container_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/environments/${environmentId}/pods/${podName}/containers/${containerName}/logs.json`; const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/logs/k8s.json`;
Api.getPodLogs({ projectPath, environmentId, podName, containerName }) Api.getPodLogs({ projectPath, environmentName, podName, containerName })
.then(() => { .then(() => {
expect(expectedUrl).toBe(lastUrl()); expect(getRequest().url).toBe(expectedUrl);
expect(getRequest().params).toEqual({
environment_name: environmentName,
pod_name: podName,
container_name: containerName,
});
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
it('calls `axios.get` without pod_name and container_name', done => { it('calls `axios.get` without pod_name and container_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/environments/${environmentId}/pods/containers/logs.json`; const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/logs/k8s.json`;
Api.getPodLogs({ projectPath, environmentId }) Api.getPodLogs({ projectPath, environmentName })
.then(() => { .then(() => {
expect(expectedUrl).toBe(lastUrl()); expect(getRequest().url).toBe(expectedUrl);
expect(getRequest().params).toEqual({
environment_name: environmentName,
});
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
it('calls `axios.get` with pod_name', done => { it('calls `axios.get` with pod_name', done => {
const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/environments/${environmentId}/pods/${podName}/containers/logs.json`; const expectedUrl = `${dummyUrlRoot}/${projectPath}/-/logs/k8s.json`;
Api.getPodLogs({ projectPath, environmentId, podName }) Api.getPodLogs({ projectPath, environmentName, podName })
.then(() => { .then(() => {
expect(expectedUrl).toBe(lastUrl()); expect(getRequest().url).toBe(expectedUrl);
expect(getRequest().params).toEqual({
environment_name: environmentName,
pod_name: podName,
});
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
......
...@@ -49,6 +49,7 @@ describe('Environment table', () => { ...@@ -49,6 +49,7 @@ describe('Environment table', () => {
name: 'review', name: 'review',
size: 1, size: 1,
environment_path: 'url', environment_path: 'url',
project_path: 'url',
id: 1, id: 1,
hasDeployBoard: true, hasDeployBoard: true,
deployBoardData: deployBoardMockData, deployBoardData: deployBoardMockData,
......
...@@ -7,7 +7,6 @@ import { createStore } from 'ee/logs/stores'; ...@@ -7,7 +7,6 @@ import { createStore } from 'ee/logs/stores';
import { scrollDown } from '~/lib/utils/scroll_utils'; import { scrollDown } from '~/lib/utils/scroll_utils';
import { import {
mockProjectPath, mockProjectPath,
mockEnvId,
mockEnvName, mockEnvName,
mockEnvironments, mockEnvironments,
mockPods, mockPods,
...@@ -26,14 +25,14 @@ describe('EnvironmentLogs', () => { ...@@ -26,14 +25,14 @@ describe('EnvironmentLogs', () => {
const propsData = { const propsData = {
projectFullPath: mockProjectPath, projectFullPath: mockProjectPath,
environmentId: mockEnvId, environmentName: mockEnvName,
currentEnvironmentName: mockEnvName,
environmentsPath: mockEnvironmentsEndpoint, environmentsPath: mockEnvironmentsEndpoint,
}; };
const actionMocks = { const actionMocks = {
setInitData: jest.fn(), setInitData: jest.fn(),
showPodLogs: jest.fn(), showPodLogs: jest.fn(),
showEnvironment: jest.fn(),
fetchEnvironments: jest.fn(), fetchEnvironments: jest.fn(),
}; };
...@@ -75,6 +74,10 @@ describe('EnvironmentLogs', () => { ...@@ -75,6 +74,10 @@ describe('EnvironmentLogs', () => {
actionMocks.setInitData.mockReset(); actionMocks.setInitData.mockReset();
actionMocks.showPodLogs.mockReset(); actionMocks.showPodLogs.mockReset();
actionMocks.fetchEnvironments.mockReset(); actionMocks.fetchEnvironments.mockReset();
if (wrapper) {
wrapper.destroy();
}
}); });
it('displays UI elements', () => { it('displays UI elements', () => {
...@@ -95,16 +98,13 @@ describe('EnvironmentLogs', () => { ...@@ -95,16 +98,13 @@ describe('EnvironmentLogs', () => {
expect(actionMocks.setInitData).toHaveBeenCalledTimes(1); expect(actionMocks.setInitData).toHaveBeenCalledTimes(1);
expect(actionMocks.setInitData).toHaveBeenLastCalledWith({ expect(actionMocks.setInitData).toHaveBeenLastCalledWith({
environmentId: mockEnvId,
projectPath: mockProjectPath, projectPath: mockProjectPath,
environmentName: mockEnvName,
podName: null, podName: null,
}); });
expect(actionMocks.fetchEnvironments).toHaveBeenCalledTimes(1); expect(actionMocks.fetchEnvironments).toHaveBeenCalledTimes(1);
expect(actionMocks.fetchEnvironments).toHaveBeenLastCalledWith(mockEnvironmentsEndpoint); expect(actionMocks.fetchEnvironments).toHaveBeenLastCalledWith(mockEnvironmentsEndpoint);
expect(findEnvironmentsDropdown().props('text')).toBe(mockEnvName);
expect(findPodsDropdown().props('text').length).toBeGreaterThan(0);
}); });
describe('loading state', () => { describe('loading state', () => {
...@@ -148,6 +148,7 @@ describe('EnvironmentLogs', () => { ...@@ -148,6 +148,7 @@ describe('EnvironmentLogs', () => {
beforeEach(() => { beforeEach(() => {
actionMocks.setInitData.mockImplementation(() => { actionMocks.setInitData.mockImplementation(() => {
state.pods.options = mockPods; state.pods.options = mockPods;
state.environments.current = mockEnvName;
[state.pods.current] = state.pods.options; [state.pods.current] = state.pods.options;
state.logs.isComplete = false; state.logs.isComplete = false;
...@@ -178,14 +179,11 @@ describe('EnvironmentLogs', () => { ...@@ -178,14 +179,11 @@ describe('EnvironmentLogs', () => {
it('populates environments dropdown', () => { it('populates environments dropdown', () => {
const items = findEnvironmentsDropdown().findAll(GlDropdownItem); const items = findEnvironmentsDropdown().findAll(GlDropdownItem);
expect(findEnvironmentsDropdown().props('text')).toBe(mockEnvName); expect(findEnvironmentsDropdown().props('text')).toBe(mockEnvName);
expect(items.length).toBe(mockEnvironments.length); expect(items.length).toBe(mockEnvironments.length);
mockEnvironments.forEach((env, i) => { mockEnvironments.forEach((env, i) => {
const item = items.at(i); const item = items.at(i);
expect(item.text()).toBe(env.name); expect(item.text()).toBe(env.name);
expect(item.attributes('href')).toBe(env.logs_path);
}); });
}); });
...@@ -215,6 +213,18 @@ describe('EnvironmentLogs', () => { ...@@ -215,6 +213,18 @@ describe('EnvironmentLogs', () => {
}); });
describe('when user clicks', () => { describe('when user clicks', () => {
it('environment name, trace is refreshed', () => {
const items = findEnvironmentsDropdown().findAll(GlDropdownItem);
const index = 1; // any env
expect(actionMocks.showEnvironment).toHaveBeenCalledTimes(0);
items.at(index).vm.$emit('click');
expect(actionMocks.showEnvironment).toHaveBeenCalledTimes(1);
expect(actionMocks.showEnvironment).toHaveBeenLastCalledWith(mockEnvironments[index].name);
});
it('pod name, trace is refreshed', () => { it('pod name, trace is refreshed', () => {
const items = findPodsDropdown().findAll(GlDropdownItem); const items = findPodsDropdown().findAll(GlDropdownItem);
const index = 2; // any pod const index = 2; // any pod
......
...@@ -10,12 +10,12 @@ import flash from '~/flash'; ...@@ -10,12 +10,12 @@ import flash from '~/flash';
import { import {
mockProjectPath, mockProjectPath,
mockEnvId,
mockPodName, mockPodName,
mockEnvironmentsEndpoint, mockEnvironmentsEndpoint,
mockEnvironments, mockEnvironments,
mockPods, mockPods,
mockLines, mockLines,
mockEnvName,
} from '../mock_data'; } from '../mock_data';
jest.mock('~/flash'); jest.mock('~/flash');
...@@ -36,13 +36,11 @@ describe('Logs Store actions', () => { ...@@ -36,13 +36,11 @@ describe('Logs Store actions', () => {
it('should commit environment and pod name mutation', done => { it('should commit environment and pod name mutation', done => {
testAction( testAction(
setInitData, setInitData,
{ projectPath: mockProjectPath, environmentId: mockEnvId, podName: mockPodName }, { projectPath: mockProjectPath, environmentName: mockEnvName, podName: mockPodName },
state, state,
[ [
{ { type: types.SET_PROJECT_PATH, payload: mockProjectPath },
type: types.SET_PROJECT_ENVIRONMENT, { type: types.SET_PROJECT_ENVIRONMENT, payload: mockEnvName },
payload: { projectPath: mockProjectPath, environmentId: mockEnvId },
},
{ type: types.SET_CURRENT_POD_NAME, payload: mockPodName }, { type: types.SET_CURRENT_POD_NAME, payload: mockPodName },
], ],
[{ type: 'fetchLogs' }], [{ type: 'fetchLogs' }],
...@@ -114,12 +112,14 @@ describe('Logs Store actions', () => { ...@@ -114,12 +112,14 @@ describe('Logs Store actions', () => {
it('should commit logs and pod data when there is pod name defined', done => { it('should commit logs and pod data when there is pod name defined', done => {
state.projectPath = mockProjectPath; state.projectPath = mockProjectPath;
state.environments.current = mockEnvId; state.environments.current = mockEnvName;
state.pods.current = mockPodName; state.pods.current = mockPodName;
const endpoint = `/${mockProjectPath}/-/environments/${mockEnvId}/pods/${mockPodName}/containers/logs.json`; const endpoint = `/${mockProjectPath}/-/logs/k8s.json`;
mock.onGet(endpoint).reply(200, { mock
.onGet(endpoint, { params: { environment_name: mockEnvName, pod_name: mockPodName } })
.reply(200, {
pod_name: mockPodName, pod_name: mockPodName,
pods: mockPods, pods: mockPods,
logs: mockLines, logs: mockLines,
...@@ -145,11 +145,11 @@ describe('Logs Store actions', () => { ...@@ -145,11 +145,11 @@ describe('Logs Store actions', () => {
it('should commit logs and pod data when no pod name defined', done => { it('should commit logs and pod data when no pod name defined', done => {
state.projectPath = mockProjectPath; state.projectPath = mockProjectPath;
state.environments.current = mockEnvId; state.environments.current = mockEnvName;
const endpoint = `/${mockProjectPath}/-/environments/${mockEnvId}/pods/containers/logs.json`; const endpoint = `/${mockProjectPath}/-/logs/k8s.json`;
mock.onGet(endpoint).reply(200, { mock.onGet(endpoint, { params: { environment_name: mockEnvName } }).reply(200, {
pod_name: mockPodName, pod_name: mockPodName,
pods: mockPods, pods: mockPods,
logs: mockLines, logs: mockLines,
...@@ -174,9 +174,9 @@ describe('Logs Store actions', () => { ...@@ -174,9 +174,9 @@ describe('Logs Store actions', () => {
it('should commit logs and pod errors when backend fails', done => { it('should commit logs and pod errors when backend fails', done => {
state.projectPath = mockProjectPath; state.projectPath = mockProjectPath;
state.environments.current = mockEnvId; state.environments.current = mockEnvName;
const endpoint = `/${mockProjectPath}/-/environments/${mockEnvId}/pods/containers/logs.json`; const endpoint = `/${mockProjectPath}/logs.json?environment_name=${mockEnvName}`;
mock.onGet(endpoint).replyOnce(500); mock.onGet(endpoint).replyOnce(500);
testAction( testAction(
......
...@@ -4,7 +4,7 @@ import * as types from 'ee/logs/stores/mutation_types'; ...@@ -4,7 +4,7 @@ import * as types from 'ee/logs/stores/mutation_types';
import logsPageState from 'ee/logs/stores/state'; import logsPageState from 'ee/logs/stores/state';
import { import {
mockProjectPath, mockProjectPath,
mockEnvId, mockEnvName,
mockEnvironments, mockEnvironments,
mockPods, mockPods,
mockPodName, mockPodName,
...@@ -25,13 +25,14 @@ describe('Logs Store Mutations', () => { ...@@ -25,13 +25,14 @@ describe('Logs Store Mutations', () => {
}); });
describe('SET_PROJECT_ENVIRONMENT', () => { describe('SET_PROJECT_ENVIRONMENT', () => {
it('sets the logs json endpoint', () => { it('sets the project path', () => {
mutations[types.SET_PROJECT_ENVIRONMENT](state, { mutations[types.SET_PROJECT_PATH](state, mockProjectPath);
projectPath: mockProjectPath,
environmentId: mockEnvId,
});
expect(state.projectPath).toEqual(mockProjectPath); expect(state.projectPath).toEqual(mockProjectPath);
expect(state.environments.current).toEqual(mockEnvId); });
it('sets the environment', () => {
mutations[types.SET_PROJECT_ENVIRONMENT](state, mockEnvName);
expect(state.environments.current).toEqual(mockEnvName);
}); });
}); });
......
...@@ -36,7 +36,7 @@ describe EnvironmentsHelper do ...@@ -36,7 +36,7 @@ describe EnvironmentsHelper do
it 'returns environment parameters data' do it 'returns environment parameters data' do
expect(subject).to include( expect(subject).to include(
"current-environment-name": environment.name, "environment-name": environment.name,
"environments-path": project_environments_path(project, format: :json) "environments-path": project_environments_path(project, format: :json)
) )
end end
......
...@@ -4,6 +4,8 @@ import DeployBoard from 'ee/environments/components/deploy_board_component.vue'; ...@@ -4,6 +4,8 @@ import DeployBoard from 'ee/environments/components/deploy_board_component.vue';
import { environment } from 'spec/environments/mock_data'; import { environment } from 'spec/environments/mock_data';
import { deployBoardMockData } from './mock_data'; import { deployBoardMockData } from './mock_data';
const projectPath = 'gitlab-org/gitlab-test';
describe('Deploy Board', () => { describe('Deploy Board', () => {
let wrapper; let wrapper;
...@@ -13,7 +15,8 @@ describe('Deploy Board', () => { ...@@ -13,7 +15,8 @@ describe('Deploy Board', () => {
deployBoardData: deployBoardMockData, deployBoardData: deployBoardMockData,
isLoading: false, isLoading: false,
isEmpty: false, isEmpty: false,
logsPath: environment.log_path, projectPath,
environmentName: environment.name,
...props, ...props,
}, },
sync: false, sync: false,
...@@ -60,7 +63,8 @@ describe('Deploy Board', () => { ...@@ -60,7 +63,8 @@ describe('Deploy Board', () => {
deployBoardData: {}, deployBoardData: {},
isLoading: false, isLoading: false,
isEmpty: true, isEmpty: true,
logsPath: environment.log_path, projectPath,
environmentName: environment.name,
}); });
wrapper.vm.$nextTick(done); wrapper.vm.$nextTick(done);
}); });
...@@ -79,7 +83,8 @@ describe('Deploy Board', () => { ...@@ -79,7 +83,8 @@ describe('Deploy Board', () => {
deployBoardData: {}, deployBoardData: {},
isLoading: true, isLoading: true,
isEmpty: false, isEmpty: false,
logsPath: environment.log_path, projectPath,
environmentName: environment.name,
}); });
wrapper.vm.$nextTick(done); wrapper.vm.$nextTick(done);
}); });
...@@ -94,7 +99,8 @@ describe('Deploy Board', () => { ...@@ -94,7 +99,8 @@ describe('Deploy Board', () => {
wrapper = createComponent({ wrapper = createComponent({
isLoading: false, isLoading: false,
isEmpty: false, isEmpty: false,
logsPath: environment.log_path, projectPath,
environmentName: environment.name,
hasLegacyAppLabel: true, hasLegacyAppLabel: true,
deployBoardData: {}, deployBoardData: {},
}); });
......
...@@ -12,7 +12,7 @@ export const environmentsList = [ ...@@ -12,7 +12,7 @@ export const environmentsList = [
stop_path: '/root/review-app/environments/7/stop', stop_path: '/root/review-app/environments/7/stop',
created_at: '2017-01-31T10:53:46.894Z', created_at: '2017-01-31T10:53:46.894Z',
updated_at: '2017-01-31T10:53:46.894Z', updated_at: '2017-01-31T10:53:46.894Z',
log_path: '/root/review-app/environments/7/logs', project_path: '/root/review-app',
rollout_status: {}, rollout_status: {},
}, },
{ {
...@@ -29,7 +29,7 @@ export const environmentsList = [ ...@@ -29,7 +29,7 @@ export const environmentsList = [
stop_path: '/root/review-app/environments/12/stop', stop_path: '/root/review-app/environments/12/stop',
created_at: '2017-02-01T19:42:18.400Z', created_at: '2017-02-01T19:42:18.400Z',
updated_at: '2017-02-01T19:42:18.400Z', updated_at: '2017-02-01T19:42:18.400Z',
log_path: '/root/review-app/environments/12/logs', project_path: '/root/review-app',
rollout_status: {}, rollout_status: {},
}, },
]; ];
...@@ -140,5 +140,5 @@ export const folder = { ...@@ -140,5 +140,5 @@ export const folder = {
created_at: '2017-02-01T19:42:18.400Z', created_at: '2017-02-01T19:42:18.400Z',
updated_at: '2017-02-01T19:42:18.400Z', updated_at: '2017-02-01T19:42:18.400Z',
rollout_status: {}, rollout_status: {},
log_path: '/root/review-app/environments/12/logs', project_path: '/root/review-app',
}; };
...@@ -23,7 +23,7 @@ describe('Deploy Board Instance', () => { ...@@ -23,7 +23,7 @@ describe('Deploy Board Instance', () => {
it('should render a div with the correct css status and tooltip data', () => { it('should render a div with the correct css status and tooltip data', () => {
wrapper = createComponent({ wrapper = createComponent({
logsPath: folder.log_path, projectPath: folder.project_path,
tooltipText: 'This is a pod', tooltipText: 'This is a pod',
}); });
...@@ -46,12 +46,13 @@ describe('Deploy Board Instance', () => { ...@@ -46,12 +46,13 @@ describe('Deploy Board Instance', () => {
it('should have a log path computed with a pod name as a parameter', () => { it('should have a log path computed with a pod name as a parameter', () => {
wrapper = createComponent({ wrapper = createComponent({
logsPath: folder.log_path, projectPath: folder.project_path,
environmentName: 'foo',
podName: 'tanuki-1', podName: 'tanuki-1',
}); });
expect(wrapper.vm.computedLogPath).toEqual( expect(wrapper.vm.computedLogPath).toEqual(
'/root/review-app/environments/12/logs?pod_name=tanuki-1', '/root/review-app/-/logs?environment_name=foo&pod_name=tanuki-1',
); );
}); });
}); });
...@@ -78,10 +79,10 @@ describe('Deploy Board Instance', () => { ...@@ -78,10 +79,10 @@ describe('Deploy Board Instance', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('should not be a link without a logsPath prop', done => { it('should not be a link without a projectPath prop', done => {
wrapper = createComponent({ wrapper = createComponent({
stable: false, stable: false,
logsPath: '', projectPath: '',
}); });
wrapper.vm.$nextTick(() => { wrapper.vm.$nextTick(() => {
......
...@@ -23,7 +23,7 @@ describe Gitlab::EtagCaching::Router do ...@@ -23,7 +23,7 @@ describe Gitlab::EtagCaching::Router do
context 'k8s pod logs' do context 'k8s pod logs' do
it 'matches with pod_name and container_name' do it 'matches with pod_name and container_name' do
result = described_class.match( result = described_class.match(
'/environments/7/pods/pod_name/containers/container_name/logs.json' '/environments/7/pods/pod_name/containers/container_name/logs/k8s.json'
) )
expect(result).to be_present expect(result).to be_present
...@@ -32,7 +32,7 @@ describe Gitlab::EtagCaching::Router do ...@@ -32,7 +32,7 @@ describe Gitlab::EtagCaching::Router do
it 'matches with pod_name' do it 'matches with pod_name' do
result = described_class.match( result = described_class.match(
'/environments/7/pods/pod_name/containers/logs.json' '/environments/7/pods/pod_name/containers/logs/k8s.json'
) )
expect(result).to be_present expect(result).to be_present
...@@ -41,7 +41,7 @@ describe Gitlab::EtagCaching::Router do ...@@ -41,7 +41,7 @@ describe Gitlab::EtagCaching::Router do
it 'matches without pod_name and container_name' do it 'matches without pod_name and container_name' do
result = described_class.match( result = described_class.match(
'/environments/7/pods/containers/logs.json' '/environments/7/pods/containers/logs/k8s.json'
) )
expect(result).to be_present expect(result).to be_present
......
...@@ -317,11 +317,11 @@ describe Clusters::Platforms::Kubernetes do ...@@ -317,11 +317,11 @@ describe Clusters::Platforms::Kubernetes do
expect_next_instance_of(Gitlab::EtagCaching::Store) do |store| expect_next_instance_of(Gitlab::EtagCaching::Store) do |store|
expect(store).to receive(:touch) expect(store).to receive(:touch)
.with( .with(
::Gitlab::Routing.url_helpers.k8s_pod_logs_project_environment_path( ::Gitlab::Routing.url_helpers.k8s_project_logs_path(
environment.project, environment.project,
environment, environment_name: environment.name,
opts['pod_name'], pod_name: opts['pod_name'],
opts['container_name'], container_name: opts['container_name'],
format: :json format: :json
) )
) )
......
...@@ -106,7 +106,7 @@ describe 'layouts/nav/sidebar/_project' do ...@@ -106,7 +106,7 @@ describe 'layouts/nav/sidebar/_project' do
let(:can_read_pod_logs) { true } let(:can_read_pod_logs) { true }
it 'link is visible ' do it 'link is visible ' do
expect(rendered).to have_link('Pod logs', href: logs_project_environments_path(project)) expect(rendered).to have_link('Pod logs', href: project_logs_path(project))
end end
end end
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
"stop_path": { "type": "string" }, "stop_path": { "type": "string" },
"cancel_auto_stop_path": { "type": "string" }, "cancel_auto_stop_path": { "type": "string" },
"folder_path": { "type": "string" }, "folder_path": { "type": "string" },
"project_path": { "type": "string" },
"created_at": { "type": "string", "format": "date-time" }, "created_at": { "type": "string", "format": "date-time" },
"updated_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" },
"auto_stop_at": { "type": "string", "format": "date-time" }, "auto_stop_at": { "type": "string", "format": "date-time" },
......
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