追求完美不服输的我,一直在与各种问题斗争的路上痛并快乐着

上一篇文章Django实现WebSSH操作Kubernetes Pod最后留了个问题没有解决,那就是terminal内容窗口的大小没有办法调整,这会导致的一个问题就是浏览器上可显示内容的区域太小,当查看/编辑文件时非常不便,就像下边这样,红色可视区域并没有被用到

RESIZE_CHANNEL

前文说到kubectl exec有两个参数COLUMNSLINES可以调整tty内容窗口的大小,命令如下:

  1. kubectl exec -i -t $1 env COLUMNS=$COLUMNS LINES=$LINES bash

这实际上就是将COLUMNSLINES两个环境变量传递到了容器内,由于Kubernetes stream底层也是通过kubernetes exec实现的,所以我们在启动容器时也将这两个变量传递进去就可以了,就像这样

  1. exec_command = [
  2. "/bin/sh",
  3. "-c",
  4. 'export LINES=20; export COLUMNS=100; '
  5. 'TERM=xterm-256color; export TERM; [ -x /bin/bash ] '
  6. '&& ([ -x /usr/bin/script ] '
  7. '&& /usr/bin/script -q -c "/bin/bash" /dev/null || exec /bin/bash) '
  8. '|| exec /bin/sh']

添加了export LINES=20; export COLUMNS=100;,可以实现改变tty的输出大小,但这有个问题就是只能在建立链接时指定一次,不能动态的更新,也就是在一次websocket会话的过程中,如果页面大小改变了,后端输出的LINES和COLUMNS是无法随着改变的

在解决问题的过程中发现官方源码中有个RESIZE_CHANNEL的配置,同样可以控制窗口的大小,使用方法如下:

  1. cont_stream = stream(api_instance.connect_get_namespaced_pod_exec,
  2. name=pod_name,
  3. namespace=self.namespace,
  4. container=container,
  5. command=exec_command,
  6. stderr=True, stdin=True,
  7. stdout=True, tty=True,
  8. _preload_content=False
  9. )
  10. cont_stream.write_channel(4, json.dumps({"Height": int(rows), "Width": int(cols)}))

这样我们就可以修改stream输出的窗口大小了

xterm.js fit

一顿操作后,打开页面,咦?怎么页面不行,原来窗口的调整不仅需要调整stream输出数据的窗口大小,前端页面也要跟着一并调整

这里用到了xterm.js的另一个组件fit,fit可以调整终端大小的colsrows适配父级元素

首先调整terminal块的宽度和高度为整个页面可视区域的大小,要让整个可视区域为终端窗口

  1. document.getElementById('terminal').style.height = window.innerHeight + 'px';

然后引入fit组件,在term初始化之后执行fit操作

  1. <script src="/static/plugins/xterm/xterm.js"></script>
  2. <script src="/static/plugins/xterm/addons/fit/fit.js"></script>
  3. <script>
  4. // 修改terminal的高度为body的高度
  5. document.getElementById('terminal').style.height = window.innerHeight + 'px';
  6. var term = new Terminal({cursorBlink: true});
  7. term.open(document.getElementById('terminal'));
  8. // xterm fullscreen config
  9. Terminal.applyAddon(fit);
  10. term.fit();
  11. console.log(term.cols, term.rows);
  12. </script>

fit之后就可以通过term.colsterm.rows取到xterm.js根据字体大小自动计算过的colsrows的值了,然后把这两个值传递给kubernetes,kubernetes再根据这两个值输出窗口大小,这样前后端匹配就完美了

数据传递

xterm.js可以通过如下的方法动态的将colsrows传递给后端

  1. term.on('resize', size => {
  2. socket.send('resize', [size.cols, size.rows]);
  3. })

但当窗口由大变小时,之前输出的内容会有样式错乱,我为了方便直接在WebSocket连接建立时采用url传参的方式把colsrows两个值传递给后端,kubernetes根据这两个值来设置输出内容的窗口大小,这样做的缺点是不会随着前端页面的变化动态的去调整后端stream输出窗口的大小,不过问题不大,如果页面调整大小,刷新下页面重新建立连接就可以啦,具体实现如下

首先需要修改的就是WebSocket的url地址

前端增加term.colsterm.rows两个参数的传递

  1. var socket = new WebSocket(
  2. 'ws://' + window.location.host + '/pod/{{ name }}/'+term.cols+'/'+term.rows);

Routing增加两个参数的解析

  1. re_path(r'^pod/(?P<name>\w+)/(?P<cols>\d+)/(?P<rows>\d+)$', SSHConsumer),

Consumer解析URL将对应参数传递给Kubernetes stream

  1. class SSHConsumer(WebsocketConsumer):
  2. def connect(self):
  3. self.name = self.scope["url_route"]["kwargs"]["name"]
  4. self.cols = self.scope["url_route"]["kwargs"]["cols"]
  5. self.rows = self.scope["url_route"]["kwargs"]["rows"]
  6. # kube exec
  7. self.stream = KubeApi().pod_exec(self.name, cols=self.cols, rows=self.rows)
  8. kub_stream = K8SStreamThread(self, self.stream)
  9. kub_stream.start()
  10. self.accept()

最后Kubernetes stream接收参数并修改窗口大小

  1. def pod_exec(self, RAND, container="", rows=24, cols=80):
  2. api_instance = client.CoreV1Api()
  3. exec_command = [
  4. "/bin/sh",
  5. "-c",
  6. 'TERM=xterm-256color; export TERM; [ -x /bin/bash ] '
  7. '&& ([ -x /usr/bin/script ] '
  8. '&& /usr/bin/script -q -c "/bin/bash" /dev/null || exec /bin/bash) '
  9. '|| exec /bin/sh']
  10. cont_stream = stream(api_instance.connect_get_namespaced_pod_exec,
  11. name=pod_name,
  12. namespace=self.namespace,
  13. container=container,
  14. command=exec_command,
  15. stderr=True, stdin=True,
  16. stdout=True, tty=True,
  17. _preload_content=False
  18. )
  19. cont_stream.write_channel(4, json.dumps({"Height": int(rows), "Width": int(cols)}))
  20. return cont_stream

至此,每次WebSocket连接建立,前后端就会有一样的输出窗口大小,问题解决~


相关文章推荐阅读:

Python Django撸个WebSSH操作Kubernetes Pod(下)- 终端窗口自适应Resize的更多相关文章

  1. Python Django撸个WebSSH操作Kubernetes Pod

    优秀的系统都是根据反馈逐渐完善出来的 上篇文章介绍了我们为了应对安全和多分支频繁测试的问题而开发了一套Alodi系统,Alodi可以通过一个按钮快速构建一套测试环境,生成一个临时访问地址,详细信息可以 ...

  2. Kubernetes WebSSH终端窗口自适应Resize

    追求完美不服输的我,一直在与各种问题斗争的路上痛并快乐着 上一篇文章Django实现WebSSH操作Kubernetes Pod最后留了个问题没有解决,那就是terminal内容窗口的大小没有办法调整 ...

  3. Django实现WebSSH操作Kubernetes Pod

    优秀的系统都是根据反馈逐渐完善出来的 上篇文章介绍了我们为了应对安全和多分支频繁测试的问题而开发了一套Alodi系统,Alodi可以通过一个按钮快速构建一套测试环境,生成一个临时访问地址,详细信息可以 ...

  4. Python/Django(CBV/FBV/ORM操作)

    Python/Django(CBV/FBV/ORM操作) CBV:url对应的类(模式) ##====================================CBV操作============ ...

  5. [python][django学习篇][6]操作数据库

    查询(取)数据 >>> Category.objects.all() <QuerySet [<Category: Category object>]> > ...

  6. Python - Django - ORM 多对多操作

    models.py: from django.db import models # 出版社 class Publisher(models.Model): id = models.AutoField(p ...

  7. Python - Django - ORM 外键操作

    models.py: from django.db import models # 出版社 class Publisher(models.Model): id = models.AutoField(p ...

  8. Django实现WebSSH操作物理机或虚拟机

    我想用它替换掉xshell.crt之类的工具 WebSSH操作物理机或虚拟机 Django实现WebSSH操作Kubernetes Pod文章发布后,有小伙伴说咖啡哥,我们现在还没有用上Kuberne ...

  9. 基于Python+Django的Kubernetes集群管理平台

    ➠更多技术干货请戳:听云博客 时至今日,接触kubernetes也有一段时间了,而我们的大部分业务也已经稳定地运行在不同规模的kubernetes集群上,不得不说,无论是从应用部署.迭代,还是从资源调 ...

随机推荐

  1. Tensorflow 错误集锦

    文章目录 参考文献 本文记录笔者在Tensorflow使用上的一些错误的集锦,方便后来人迅速查阅解决问题. 我是留白. 我是留白. CreateSession still waiting for re ...

  2. 自研测试框架ktest介绍(适用于UI和API)

    iTesting,爱测试,爱分享 在自动化测试的过程中,测试框架是我们绕不过去的一个工具,无论你是不需要写代码直接改动数据生成脚本,还是你需要检查测试结果甚至持续集成,测试框架都在发挥它的作用. 不同 ...

  3. Hexo next主题安装algolia

    一直在使用hexo写自己的博客,最近博客刚刚搬家重新搞了下博客: 1.为hexo添加站内搜索 我用的是algolia,在next主题5.x以上的版本集成了algolia站内搜索功能,我们只需要简单的配 ...

  4. Louis的「每周语文」

    说明:此专栏为Louis收录的经典语录及书影音标记,每周一更新. 成长的本质是变得复杂.当你的主观世界遇到客观世界,之间的那条沟,你掉进去,叫挫折,爬出来,叫成长. -- 语出罗振宇在奇葩说第四季的结 ...

  5. linux学习--2.文件管理的基本命令

    文件的基本操作 前言: 看完这篇图文我应该能保证读者在Linux系统下对文件的操作能跟用Windows环境下一样流畅吧,好了下面正文 正文: 基础知识: linux里共有以下几类文件,分别为目录(di ...

  6. 达拉草201771010105《面向对象程序设计(java)》第三周学习总结

    达拉草201771010105«面向对象程序设计(java)»第三周学习总结 第一部分:实验部分  1.实验目的与要求 (1)进一步掌握Eclipse集成开发环境下java程序开发基本步骤: (2)熟 ...

  7. 在命令行中使用pushd和popd进行快速切换目录

    当频繁的切换三个或三个以上的目录的时候,可以使用pushd命令.每次使用目录路径被存储在栈中,然后用pushd和popd操作在目录之间切换. 例如: [root@gameserver1 ~]# pus ...

  8. 统计 Django 项目的测试覆盖率

    作者:HelloGitHub-追梦人物 文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 我们完成了对 blog 应用和 comment 应用这两个核心 app 的测试.现在 ...

  9. javascript常用工具函数总结(不定期补充)未指定标题的文章

    前言 以下代码来自:自己写的.工作项目框架上用到的.其他框架源码上的.网上看到的. 主要是作为工具函数,服务于框架业务,自身不依赖于其他框架类库,部分使用到es6/es7的语法使用时要注意转码 虽然尽 ...

  10. Ubuntu18.04LTS 文件系统简记

    Ubuntu18.04LTS 文件系统 了解Linux文件系统是熟悉掌握使用Linux系统的第一步 首先安装名为tree的工具 sudo apt install tree 运行 tree --help ...