Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/__tests__/reducers/features.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe('featureReducer', () => {
[FLAGS.MACHINE_AUTOSCALER]: false,
[FLAGS.CONSOLE_CLI_DOWNLOAD]: false,
[FLAGS.CONSOLE_NOTIFICATION]: false,
[FLAGS.CONSOLE_LOG_LINK]: false,
}));
});
});
Expand Down
5 changes: 1 addition & 4 deletions frontend/public/components/build-logs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,13 @@ export class BuildLogs extends React.Component {

render() {
const { obj: build } = this.props;
const { name, namespace } = build.metadata;
const isPipeline = _.get(build, 'spec.strategy.type') === BuildStrategyType.JenkinsPipeline;

return <div className="co-m-pane__body">
{ isPipeline
? <PipelineLogMessage build={build} />
: <ResourceLog
kind="Build"
namespace={namespace}
resourceName={name}
resource={build}
resourceStatus={this.state.status}
/>
}
Expand Down
6 changes: 1 addition & 5 deletions frontend/public/components/pod-logs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ export class PodLogs extends React.Component {

render() {
const { containers, currentKey, initContainers } = this.state;
const namespace = _.get(this.props.obj, 'metadata.namespace');
const podName = _.get(this.props.obj, 'metadata.name');
const currentContainer = _.get(containers, currentKey) || _.get(initContainers, currentKey);
const currentContainerStatus = containerToLogSourceStatus(currentContainer);
const containerDropdown = <ContainerDropdown
Expand All @@ -81,10 +79,8 @@ export class PodLogs extends React.Component {
return <div className="co-m-pane__body">
<ResourceLog
containerName={currentContainer ? currentContainer.name : ''}
kind="Pod"
dropdown={containerDropdown}
namespace={namespace}
resourceName={podName}
resource={this.props.obj}
resourceStatus={currentContainerStatus}
/>
</div>;
Expand Down
74 changes: 59 additions & 15 deletions frontend/public/components/utils/resource-log.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ import * as React from 'react';
import { Base64 } from 'js-base64';
import { saveAs } from 'file-saver';
import { Alert, AlertActionLink } from '@patternfly/react-core';
import * as _ from 'lodash-es';

import { LoadingInline, LogWindow, TogglePlay } from './';
import { LoadingInline, LogWindow, TogglePlay, ExternalLink } from './';
import * as classNames from 'classnames';
import { modelFor, resourceURL } from '../../module/k8s';
import { WSFactory } from '../../module/ws-factory';
import { LineBuffer } from './line-buffer';
import * as screenfull from 'screenfull';
import { k8sGet } from '@console/internal/module/k8s';
import { ConsoleLogLinkModel } from '@console/internal/models';
import { FLAGS } from '../../const';
import { connectToFlags } from '../../reducers/features';

export const STREAM_EOF = 'eof';
export const STREAM_LOADING = 'loading';
Expand All @@ -30,7 +35,7 @@ const streamStatusMessages = {
};

// Component for log stream controls
const LogControls = ({dropdown, onDownload, toggleFullscreen, isFullscreen, status, toggleStreaming}) => {
const LogControls = ({dropdown, onDownload, toggleFullscreen, isFullscreen, status, toggleStreaming, resource, containerName, podLogLinks}) => {
const expandCompressClass = classNames('fa', {
'fa-expand': !isFullscreen,
'fa-compress': isFullscreen,
Expand All @@ -45,6 +50,33 @@ const LogControls = ({dropdown, onDownload, toggleFullscreen, isFullscreen, stat
{dropdown && <div className="co-toolbar__item">{dropdown}</div>}
</div>
<div className="co-toolbar__group co-toolbar__group--right">
{!_.isEmpty(podLogLinks) && _.map(_.sortBy(podLogLinks, 'metadata.name'), (link, i) => {
const namespace = resource.metadata.namespace;
const namespaceFilter = link.spec.namespaceFilter;
const hrefTemplate = link.spec.hrefTemplate;
const labels = resource.metadata.labels;
// if namespaceFilter, do not output link if namespace does not match namespaceFilter regex
if (namespaceFilter && namespace.search(namespaceFilter) === -1) {
return null;
}
const compiled = _.attempt(() => _.template(hrefTemplate));
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding @spadgett's comment back after code changes:

If we can't find a way to prevent code execution with _.template, we could fall back to...

template
  .replace('${name}', encodeURIComponent(resource.metadata.name))
  .replace('${container}', encodeURIComponent(containerName))
  // ...

if (_.isError(compiled)) {
// eslint-disable-next-line no-console
console.log('Invalid hrefTemplate: ', hrefTemplate);
return null;
}
const url = compiled({
'name': resource.metadata.name,
'uid': resource.metadata.uid,
'container': containerName,
namespace,
'labels': _.map(_.keys(labels), k => `${encodeURIComponent(k)}=${encodeURIComponent(labels[k])}`).join('|'),
});
return <React.Fragment key={`${resource.metadata.uid}-${i}`}>
<ExternalLink href={url} text={link.spec.text} additionalClassName="co-external-link--within-toolbar btn btn-link" />
<span aria-hidden="true" className="co-action-divider hidden-xs">|</span>
</React.Fragment>;
})}
<button className="btn btn-link" onClick={onDownload}>
<i className="fa fa-download" aria-hidden="true"></i>&nbsp;Download
</button>
Expand All @@ -57,7 +89,7 @@ const LogControls = ({dropdown, onDownload, toggleFullscreen, isFullscreen, stat
};

// Resource agnostic log component
export class ResourceLog extends React.Component {
class ResourceLog_ extends React.Component {
constructor(props) {
super(props);
this._buffer = new LineBuffer(props.bufferSize);
Expand Down Expand Up @@ -95,7 +127,16 @@ export class ResourceLog extends React.Component {
return null;
}

fetchLogLinks() {
k8sGet(ConsoleLogLinkModel)
.then(podLogLinks => this.setState({podLogLinks: podLogLinks.items}))
.catch(e => this.setState({error: e}));
Comment thread
rhamilto marked this conversation as resolved.
Outdated
}

componentDidMount() {
if (this.props.flags.CONSOLE_LOG_LINK && this.props.resource.kind === 'Pod') {
this.fetchLogLinks();
}
this._wsInit(this.props);
if (screenfull.enabled) {
screenfull.on('change', () => {
Expand Down Expand Up @@ -125,9 +166,9 @@ export class ResourceLog extends React.Component {

// Download currently displayed log content
_download() {
const {resourceName, containerName} = this.props;
const {resource, containerName} = this.props;
const blob = this._buffer.getBlob({type: 'text/plain;charset=utf-8'});
let filename = resourceName;
let filename = resource.metadata.name;
if (containerName) {
filename = `${filename}-${containerName}`;
}
Expand Down Expand Up @@ -215,19 +256,19 @@ export class ResourceLog extends React.Component {
}

// Initialize websocket connection and wire up handlers
_wsInit({kind, namespace, resourceName, containerName, bufferSize}) {
_wsInit({resource, containerName, bufferSize}) {
if ([LOG_SOURCE_RUNNING, LOG_SOURCE_TERMINATED, LOG_SOURCE_RESTARTING].includes(this.state.resourceStatus)) {
const urlOpts = {
ns: namespace,
name: resourceName,
ns: resource.metadata.namespace,
name: resource.metadata.name,
path: 'log',
queryParams: {
container: containerName || '',
follow: 'true',
tailLines: bufferSize,
},
};
const watchURL = resourceURL(modelFor(kind), urlOpts);
const watchURL = resourceURL(modelFor(resource.kind), urlOpts);
const wsOpts = {
host: 'auto',
path: watchURL,
Expand All @@ -243,8 +284,8 @@ export class ResourceLog extends React.Component {
}

render() {
const {dropdown, kind, bufferSize} = this.props;
const {error, lines, linesBehind, stale, status, isFullscreen} = this.state;
const {resource, containerName, dropdown, bufferSize} = this.props;
const {error, lines, linesBehind, stale, status, isFullscreen, podLogLinks} = this.state;
const bufferFull = lines.length === bufferSize;

return <React.Fragment>
Expand All @@ -269,7 +310,10 @@ export class ResourceLog extends React.Component {
onDownload={this._download}
status={status}
toggleFullscreen={this._toggleFullscreen}
toggleStreaming={this._toggleStreaming} />
toggleStreaming={this._toggleStreaming}
resource={resource}
containerName={containerName}
podLogLinks={podLogLinks} />
<LogWindow
lines={lines}
linesBehind={linesBehind}
Expand All @@ -282,6 +326,8 @@ export class ResourceLog extends React.Component {
}
}

export const ResourceLog = connectToFlags(FLAGS.CONSOLE_LOG_LINK)(ResourceLog_);

ResourceLog.defaultProps = {
bufferSize: 1000,
};
Expand All @@ -290,8 +336,6 @@ ResourceLog.propTypes = {
bufferSize: PropTypes.number.isRequired,
containerName: PropTypes.string,
dropdown: PropTypes.element,
kind: PropTypes.string.isRequired,
namespace: PropTypes.string.isRequired,
resourceName: PropTypes.string.isRequired,
resource: PropTypes.object.isRequired,
resourceStatus: PropTypes.string.isRequired,
};
1 change: 1 addition & 0 deletions frontend/public/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export enum FLAGS {
MACHINE_AUTOSCALER = 'MACHINE_AUTOSCALER',
CONSOLE_CLI_DOWNLOAD = 'CONSOLE_CLI_DOWNLOAD',
CONSOLE_NOTIFICATION = 'CONSOLE_NOTIFICATION',
CONSOLE_LOG_LINK = 'CONSOLE_LOG_LINK',
}
13 changes: 13 additions & 0 deletions frontend/public/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -927,3 +927,16 @@ export const ConsoleNotificationModel: K8sKind = {
id: 'consolenotification',
crd: true,
};

export const ConsoleLogLinkModel: K8sKind = {
label: 'Console Log Link',
labelPlural: 'Console Log Links',
apiVersion: 'v1',
apiGroup: 'console.openshift.io',
plural: 'consoleloglinks',
abbr: 'CLL',
namespaced: false,
kind: 'ConsoleLogLink',
id: 'consoleloglink',
crd: true,
};
8 changes: 8 additions & 0 deletions frontend/public/models/yaml-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,14 @@ spec:
text: Optional link text
color: '#fff'
backgroundColor: '#0088ce'
`).setIn([referenceForModel(k8sModels.ConsoleLogLinkModel), 'default'], `
apiVersion: console.openshift.io/v1
kind: ConsoleLogLink
metadata:
name: example
spec:
hrefTemplate: 'https://example.com/logs?name=\${name}&container=\${container}&namespace=\${namespace}&labels=\${labels}'
text: Example Logs
`);

const pluginTemplates = ImmutableMap<GroupVersionKind, ImmutableMap<string, string>>()
Expand Down
2 changes: 2 additions & 0 deletions frontend/public/reducers/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
PrometheusModel,
ConsoleCLIDownloadModel,
ConsoleNotificationModel,
ConsoleLogLinkModel,
} from '../models';
import { referenceForModel } from '../module/k8s';
import { ActionType as K8sActionType } from '../actions/k8s';
Expand All @@ -36,6 +37,7 @@ export const baseCRDs = {
[referenceForModel(MachineAutoscalerModel)]: FLAGS.MACHINE_AUTOSCALER,
[referenceForModel(ConsoleCLIDownloadModel)]: FLAGS.CONSOLE_CLI_DOWNLOAD,
[referenceForModel(ConsoleNotificationModel)]: FLAGS.CONSOLE_NOTIFICATION,
[referenceForModel(ConsoleLogLinkModel)]: FLAGS.CONSOLE_LOG_LINK,
};

const CRDs = { ...baseCRDs };
Expand Down
8 changes: 7 additions & 1 deletion frontend/public/style/_common.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
$co-external-link-padding-right: 15px;

.co-m-pane__body {
margin: $grid-gutter-width 0 0;
padding: 0 ($grid-gutter-width / 2) $grid-gutter-width;
Expand Down Expand Up @@ -272,12 +274,16 @@
}
.co-external-link {
display: inline-block;
padding-right: 15px;
padding-right: $co-external-link-padding-right;
}
// Enable break word within co-m-table-grid
.co-external-link--block {
display: block;
}
// Add additional padding-right so icon doesn't abut .co-action-divider
.co-external-link--within-toolbar {
padding-right: ($co-external-link-padding-right + $padding-base-horizontal);
}

.co-toolbar {
align-items: stretch;
Expand Down