import { next } from '@ember/runloop'; import { set, setProperties, get, observer } from '@ember/object'; import { inject as service } from '@ember/service'; import Component from '@ember/component'; import Util from 'ui/utils/util'; import { alternateLabel } from 'ui/utils/platform'; import layout from './template'; import C from 'ui/utils/constants'; import { downloadFile } from 'shared/utils/download-files'; import $ from 'jquery'; import { on } from '@ember/object/evented'; const LINES = 500; var AnsiUp = null; export default Component.extend({ scope: service(), prefs: service(), layout, instance: null, alternateLabel, showProtip: true, classNames: 'container-log', status: 'connecting', containerName: null, socket: null, wrapLines: null, isFollow: true, followTimer: null, isPrevious: false, init() { this._super(...arguments); if (AnsiUp) { this._bootstrap(); } else { import('ansi_up').then( (module) => { // TODO: RC AnsiUp = module.default; this._bootstrap(); }); } }, didInsertElement() { this._super(); next(this, () => { const body = $('.log-body'); let lastScrollTop = 0; body.scroll(() => { const scrollTop = body[0].scrollTop; if ( lastScrollTop > scrollTop ) { set(this, 'isFollow', false); } lastScrollTop = scrollTop; }); var btn = $('.scroll-bottom')[0]; // eslint-disable-line if ( btn ) { btn.focus(); } }); }, willDestroyElement() { clearInterval(this.followTimer); this.disconnect(); this._super(); }, actions: { download() { const ignore = function(el, sel){ return el.clone().find( sel || '>*' ).remove().end(); }; const log = $('.log-body').children('.log-msg'); let stripped = ''; log.each((i, e) => { stripped += `${ ignore($(e), 'span').text() } \n`; }); downloadFile('container.log', stripped); }, cancel() { this.disconnect(); if (this.dismiss) { this.dismiss(); } }, clear() { var body = $('.log-body')[0]; if (body) { body.innerHTML = ''; body.scrollTop = 0; } }, scrollToTop() { $('.log-body').animate({ scrollTop: '0px' }); }, followLog() { set(this, 'isFollow', true); this.send('scrollToBottom'); }, scrollToBottom() { var body = $('.log-body'); body.stop().animate({ scrollTop: `${ body[0].scrollHeight + 1000 }px` }); }, }, wrapLinesDidChange: observer('wrapLines', function() { set(this, `prefs.${ C.PREFS.WRAP_LINES }`, this.wrapLines); }), watchReconnect: on('init', observer('containerName', 'isPrevious', function() { this.disconnect(); this.send('clear'); if (this.containerName) { this.exec(); } })), _bootstrap() { setProperties(this, { wrapLines: !!get(this, `prefs.${ C.PREFS.WRAP_LINES }`), containerName: this.containerName || get(this, 'instance.containers.firstObject.name'), }); this._initTimer(); }, _initTimer() { const followTimer = setInterval(() => { if ( this.isFollow ) { this.send('scrollToBottom'); } }, 1000); set(this, 'followTimer', followTimer); }, exec() { var instance = this.instance; const clusterId = get(this, 'scope.currentCluster.id'); const namespaceId = get(instance, 'namespaceId'); const podName = get(instance, 'name'); const containerName = this.containerName; const scheme = window.location.protocol === 'https:' ? 'wss://' : 'ws://'; let url = `${ scheme }${ window.location.host }/k8s/clusters/${ clusterId }/api/v1/namespaces/${ namespaceId }/pods/${ podName }/log`; url += `?container=${ encodeURIComponent(containerName) }&tailLines=${ LINES }&follow=true×tamps=true&previous=${ this.isPrevious }`; this.connect(url); }, connect(url) { var socket = new WebSocket(url, 'base64.binary.k8s.io'); set(this, 'socket', socket); var body = null; set(this, 'status', 'initializing'); socket.onopen = () => { set(this, 'status', 'connected'); }; socket.onmessage = (message) => { body = $('.log-body')[0]; let ansiup = new AnsiUp; set(this, 'status', 'connected'); const data = AWS.util.base64.decode(message.data).toString(); let html = ''; data.trim().split(/\n/) .filter((line) => line) .forEach((line) => { var match = line.match(/^\[?([^ \]]+)\]?\s?/); var dateStr = ''; var msg = ''; if (match && this.isDate(new Date(match[1]))) { var date = new Date(match[1]); msg = line.substr(match[0].length); dateStr = `${ Util.escapeHtml(date.toLocaleDateString()) } ${ Util.escapeHtml(date.toLocaleTimeString()) } `; } else { msg = line; } // @@TODO@@ - 10-13-17 - needed to remove the escaping here because it was being double escaped but double verify that its acutally being escaped html += `