idea自动构建web项目_构建Web应用程序以自动执行系统管理员任务

idea自动构建web项目

系统管理员(sysadmin)每年在重复性任务上浪费数千小时。 幸运的是,使用开源工具构建的Web应用程序可以自动消除很大一部分痛苦。

例如,使用Python和JavaScript构建Web应用程序只需要大约一天的时间。 这是任何Web应用程序必须具有的核心结构:

  • 后端来保留数据
  • 用于托管和路由流量的Web服务器
  • HTML用户界面
  • 交互式JavaScript代码,使其更具功能
  • CSS布局和样式使其漂亮

场景:简化员工离职

假设您是一家拥有一千名员工的公司的系统管理员。 如果普通员工在三年后离职,则必须每天裁员。 那是一个很大的时间浪费!

员工离职时有很多事情要做:从LDAP中删除其用户帐户,撤消GitHub权限,从薪资中删除他们,更新组织结构图,重定向其电子邮件,撤消其钥匙卡等。

作为系统管理员,您的任务是自动完成工作,因此您已经编写了一些辅助脚本来自动运行IT方面的内容。 但是HR仍然必须打电话给您,并要求您运行每个脚本,这是您不可以做的事情。

您决定花一整天的时间来自动解决此问题,从长远来看可以节省数百小时。 (还有另一个选项,我将在本文结尾处介绍。)

该应用程序将是您可以提供给HR的简单门户。 当HR输入离职用户的电子邮件地址时,该应用程序将在后台运行您的离职脚本。

Offboarding web app interface

它的前端是用JavaScript构建的,后端是使用Flask的Python应用程序。 它使用Nginx托管在AWS EC2实例上(或者可以在您的公司网络或私有云中)。 让我们从Python(Flask)应用程序开始依次查看每个元素。

从后端开始

后端允许您向特定的URL发出HTTP POST请求,并传入离职员工的电子邮件地址。 该应用程序为该员工运行脚本,并为每个脚本返回成功或失败。 它使用Flask (Python Web框架),非常适合像这样的轻量级后端。

要安装Flask,请创建一个Python虚拟环境,然后使用pip进行安装:


   
   
~ /offboarding$ virtualenv ~ /venv/offboarding
~ /offboarding$ source ~ /venv/offboarding/bin/activate
( offboarding ) ~ /offboarding$ pip3 install flask
Collecting flask
  Downloading
...

使用Flask处理请求

通过使用@ app.route(<url>,...) 装饰函数在Flask中创建HTTP端点,并使用request变量访问请求数据。 这是一个Flask端点,可读取员工的电子邮件地址:


   
   
#!/usr/bin/env python3

from flask import Flask , request
app = Flask ( __name__ )

@ app. route ( '/offboard' , methods = [ 'POST' ] )
def offboard ( ) :
    employee_email = request. json . get ( 'employeeEmail' )
    print ( "Running offboarding for employee {} ..." . format ( employee_email ) )
    return 'It worked!'

if __name__ == "__main__" :
    app. run ( threaded = True )

它以状态200和文本“ It work!”响应HTTP请求 在身体里。 要检查它是否有效,请运行脚本; 这将运行Flask开发服务器,足以进行测试和轻松使用(尽管有警告)。


   
   
( offboarding ) ~ /offboarding$ ./offboarding. py
 * Serving Flask app "offboarding" ( lazy loading )
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
    Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1: 5000 / ( Press CTRL+C to quit )

这是一个发出请求的curl命令:


   
   
~ $ curl -X POST \
  -d '{"employeeEmail": "shaun@anvil.works"}' \
  -H "Content-Type: application/json" \
  http://localhost: 5000 /offboard
It worked !

最后一行是服务器的响应:它正在工作! 这是服务器打印的内容:


   
   
Running offboarding for employee shaun @ anvil.works ...
127.0.0.1 - - [ 05 / Sep / 2019 13 : 10 : 55 ] "POST /offboard HTTP/1.1" 200 -

它已经启动并运行了! 您有一个可以接收数据的端点。 展开它以使其运行预先存在的辅助脚本。

使用Python运行脚本

为了使事情简单,将脚本放在单个文件夹中并遍历该文件夹,运行您发现的所有内容。 这样,您无需修改​​代码并重新启动服务器即可将新脚本添加到离职流程中。 您可以将它们复制到文件夹中(或创建符号链接)。

这是修改后的Flask应用程序的外观(代码中的注释指出了一些最佳做法):


   
   
#!/usr/bin/env python3

from flask import Flask , request
import subprocess
from pathlib import Path
import os

app = Flask ( __name__ )

# Set the (relative) path to the scripts directory
# so we can easily use a different one.
SCRIPTS_DIR = 'scripts'


@ app. route ( '/offboard' , methods = [ 'POST' ] )
def offboard ( ) :
    employee_email = request. json . get ( 'employeeEmail' )
    print ( "Running offboarding for employee {} ..." . format ( employee_email ) )

    statuses = { }

    for script in os . listdir ( SCRIPTS_DIR ) :
        # The pathlib.Path object is a really elegant way to construct paths
        # in a way that works cross-platform (IMO!)
        path = Path ( SCRIPTS_DIR ) / script
        print ( '  Running {}' . format ( path ) )

        # This is where we call out to the script and store the exit code.
        statuses [ script ] = subprocess . run ( [ str ( path ) , employee_email ] ) . returncode

    return statuses


if __name__ == "__main__" :
    # Running the Flask server in threaded mode allows multiple
    # users to connect at once. For a consumer-facing app,
    # we would not use the Flask development server, but we expect low traffic!
    app. run ( threaded = True )

将一些可执行文件放在scripts /目录中。 以下是一些执行此操作的shell命令:


   
   
mkdir -p scripts /
cat > scripts / remove_from_ldap.py <<EOF
#!/usr/bin/env python3
print('Removing user from LDAP...')
EOF

cat > scripts / revoke_github_permisisons.py <<EOF
#!/usr/bin/env python3
import sys
sys.exit(1)
EOF

cat > scripts / update_org_chart.sh <<EOF
#!/bin/sh
echo "Updating org chart for $1..."
EOF


chmod +x scripts /*

现在,重新启动服务器,然后再次运行curl请求。 响应是一个JSON对象,显示了脚本的退出代码。 看起来revoke_github_permissions.py在此运行中失败:


   
   
~ $ curl -X POST \
  -d '{"employeeEmail": "shaun@anvil.works"}' \
  -H "Content-Type: application/json" \
  http://localhost: 5000 /offboard
{ "remove_from_ldap.py" : 0 , "revoke_github_permissions.py" : 1 , "update_org_chart.sh" : 0 }

这是服务器的输出; 这次它通知我们每个脚本何时开始运行:


   
   
Running offboarding for employee shaun @ anvil.works ...
  Running scripts / remove_from_ldap.py
  Running scripts / revoke_github_permissions.py
  Running scripts / update_org_chart.sh
127.0.0.1 - - [ 05 / Sep / 2019 13 : 30 : 55 ] "POST /offboard HTTP/1.1" 200 -

现在,您可以通过发出HTTP请求来远程运行脚本。

添加身份验证和访问控制

到目前为止,该应用程序尚未执行任何访问控制,这意味着任何人都可以为任何用户触发非正式使用。 很容易看到如何滥用它,因此您需要添加一些访问控制。

在理想的情况下,您将根据公司标识系统对所有用户进行身份验证。 但是,例如根据Office 365对Flask应用进行身份验证将需要更长的时间 。 因此,请使用“ HTTP Basic”用户名和密码身份验证。

首先,安装Flask-HTTPAuth库:


   
   
( offboarding ) ~ / offboarding$ pip3 install Flask-HTTPAuth
Collecting Flask-HTTPAuth
  Downloading …

现在,通过将以下代码添加到offboarding.py的顶部,需要用户名和密码来提交表单:


   
   
from flask_httpauth import HTTPBasicAuth
from werkzeug. security import generate_password_hash , check_password_hash

app = Flask ( __name__ )
auth = HTTPBasicAuth ( )

users = {
    "hr" : generate_password_hash ( "secretpassword" ) ,
}

@ auth. verify_password
def verify_password ( username , password ) :
    if username in users:
        return check_password_hash ( users. get ( username ) , password )
    return False

@ app. route ( '/offboard' , methods = [ 'POST' ] )
@ auth. login_required
def offboard ( ) :
  # ... as before …

指定用户名和密码以使请求成功:


   
   
~ $ curl -X POST \
  -d '{"employeeEmail": "shaun@anvil.works"}' \
  -H "Content-Type: application/json" \
  http://localhost: 5000 /offboard
Unauthorized Access

ubuntu @ ip- 172 - 31 - 17 - 9 : ~ $ curl -X POST -u hr:secretpassowrd \
  -d '{"employeeEmail": "shaun@anvil.works"}' \
  -H "Content-Type: application/json" \
  http://localhost: 5000 /offboard
{ "remove_from_ldap.py" : 0 , "revoke_github_permisisons.py" : 1 , "update_org_chart.sh" : 0 }

如果人事部门乐于使用curl ,那么您将可以完成很多工作。 但是他们可能不会讲代码,因此在其上放一个前端。 为此,您必须设置一个Web服务器。

设置网络服务器

您需要Web服务器将静态内容呈现给用户。 “静态内容”是指最终由用户的Web浏览器使用的代码和数据,包括HTML,JavaScript和CSS以及图标和图像。

除非您希望整天离开工作站,并小心避免用力拉扯电源线,否则应将应用程序托管在公司的网络,私有云或其他安全的远程计算机上。 本示例将使用AWS EC2云服务器。

按照安装说明在远程计算机上安装Nginx:


   
   
sudo apt-get update
sudo apt-get install nginx

它已经可以将/ var / www / html中的任何内容提供给您,因此您可以将静态内容放入其中。

配置Nginx与Flask对话

配置它以了解Flask应用程序。 Nginx允许您配置有关URL匹配特定路径时如何托管内容的规则。 编写与确切路径/ offboard匹配的规则,并将请求转发到Flask:


   
   
# Inside the default server {} block in /etc/nginx/sites-enabled/default...
        location = / offboard {
                proxy_pass http: // 127.0.0.1: 5000 ;
        }

现在重新启动Nginx。

假设您的EC2实例位于3.8.49.253。 在浏览器中转到http://3.8.49.253时,您会看到“欢迎使用Nginx!”。 页,并且如果您针对http://3.8.49.253/offboard发出卷曲请求,您将获得与以前相同的结果。 您的应用现已在线!

还有两件事要做:

  • 购买域名并设置DNS记录( http://3.8.49.253/offboard不太漂亮!)。
  • 设置SSL,以便对流量进行加密。 如果您是在线进行的,那么“加密”是一项出色的免费服务。

您可以自己弄清楚这些步骤。 它们如何工作在很大程度上取决于您的网络配置。

编写前端以触发脚本

现在是时候编写前端HR用来访问应用程序和启动脚本的时候了。

输入框和按钮HTML

前端将显示一个文本框,HR可以使用该文本框输入离职用户的电子邮件地址,并单击一个按钮将其提交到Flask应用程序。 这是用于此HTML:


   
   
<body>
  <input type="email" id="email-box" placeholder="Enter employee email" />
  <input type="button" id="send-button" onclick="makeRequest()" value="Run" />
  <div id="status"></div>
</body>

空的<div>存储最近一次运行的结果。

将其保存到/var/www/html/offboarding/index.html ,然后浏览至http://3.8.49.253/offboarding 。 这是您得到的:

Email entry form

虽然还不是很漂亮,但是在结构上是正确的。

JavaScript和jQuery发出请求

请参阅HTML中的onclick =“ makeRequest()”以获取按钮? 它需要一个名为makeRequest的函数来使按钮在单击时调用。 此函数将数据发送到后端并处理响应。

要编写它,首先在HTML文件中添加一个<script>标记以导入jQuery ,这是一个非常有用JavaScript库,它将从您的页面提取电子邮件地址并发送请求:


   
   
<head>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
...

要使用jQuery发出HTTP POST请求:


   
   
var makeRequest = function makeRequest ( ) {
  // Make an asynchronous request to the back-end
  $ . ajax ( {
    type : "POST" ,
    url : "/offboard" ,
    data : JSON. stringify ( { "employeeEmail" : $ ( '#email-box' ) [ 0 ] . value } ) ,
    contentType : "application/json"
  } )
}

该请求是异步发出的,这意味着用户在等待响应时仍可以与该应用进行交互。 $ .ajax返回一个promise ,如果请求成功,它将运行传递给.done()方法的函数,如果请求失败,它将运行传递给.fail()方法的函数。 这些方法中的每一个都返回一个Promise,因此您可以像下面这样链接它们:

 $ . ajax ( ... ) . done ( do_x ) . fail ( do_y ) 

请求成功后,后端将返回脚本的退出代码,因此编写一个函数以针对表中的每个脚本名称显示退出代码:


   
   
function ( data ) {
  // The process has finished, we can display the statuses.
  var scriptStatuses = data ;
  $ ( '#status' ) . html (
    '<table style="width: 100%;" id="status-table"></table>'
  ) ;
  for ( script in scriptStatuses ) {
    $ ( '#status-table' ) . append (
      '<tr><td>' + script + '</td><td>' + scriptStatuses [ script ] + '</td></tr>'
    ) ;
  }
}

$('#status')。html()获取具有ID 状态HTML文档对象模型(DOM)元素,并将HTML替换为您传入的字符串。

发生故障时,使用HTTP状态代码和响应正文触发警报,以便HR人员可以引用该警报,以在应用程序停止生产时向您发出警报。 完整的脚本如下所示:


   
   
var makeRequest = function makeRequest ( ) {
  // Make an asynchronous request to the back-end
  var jqxhr = $ . ajax ( {
    type : "POST" ,
    url : "/offboard" ,
    data : JSON. stringify ( { "employeeEmail" : $ ( '#email-box' ) [ 0 ] . value } ) ,
    contentType : "application/json"
  } ) . done ( function ( data ) {
    // The process has finished, we can display the statuses.
    console. log ( data ) ;
    var scriptStatuses = data ;
    $ ( '#status' ) . html (
      '<table style="width: 100%;" id="status-table"></table>'
    ) ;
    for ( script in scriptStatuses ) {
      $ ( '#status-table' ) . append ( '<tr><td>' + script + '</td><td>' + scriptStatuses [ script ] + '</td></tr>' ) ;
    }
  } )
  . fail ( function ( data , textStatus ) {
    alert ( "error: " + data [ 'statusText' ] + " " + data [ 'responseText' ] ) ;
  } )
}

将此脚本另存为/var/www/html/offboarding/js/offboarding.js并将其包含在HTML文件中:


   
   
<head>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  <script src="js/offboarding.js"></script>
</head>
...

现在,当您输入员工的电子邮件地址并点击Run时 ,脚本将运行并在表中提供其退出代码:

Exit codes reported with 0 or 1

但是,它仍然很难看! 现在是解决该问题的时候了。

使它看起来不错

Bootstrap是一种以中立方式设计应用程序样式的好方法。 Bootstrap是一个CSS库(以及更多),它提供一个网格系统,使基于CSS的布局非常容易。 它也为您的应用程序提供了超级干净的外观。

Bootstrap的布局和样式

重组HTML,使事情最终出现在Bootstrap的行和列结构中的正确位置:列进入行,而行进入容器。 使用colrowcontainer CSS类将元素指定为列,行和容器,而card类为该行提供边框,使其看起来是独立的。

输入框放置在<form>内 ,文本框获取<label> 。 这是前端的最终HTML:


   
   
<head >
  < link href = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel = "stylesheet" / >
  < link href = "https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel = "stylesheet" / >
  <script src = "https://code.jquery.com/jquery-3.4.1.min.js" > </script >
  <script src = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" > </script >
  <script src = "js/offboarding.js" > </script >
</head >

<body >
  <div class = "container" style = "padding-top: 40px" >
    <div class = "row card" style = "padding: 20px 0" >
      <div id = "email-input" class = "col" >
        <form >
          <div class = "form-group" >
            <label for = "email-box" > Employee Email</label >
            <input type = "email" class = "form-control" id = "email-box" placeholder = "Enter employee email" / >
          </div >
            <input type = "button" class = "btn btn-primary" id = "send-button" onclick = "makeRequest()" value = "Run" / >
        </form >
        <div id = "status" > </div >
      </div >
    </div >
  </div >
</body >

现在是该应用的外观,这是一个巨大的改进。

App interface to enter employee email

添加状态图标

还有一件事:该应用程序报告状态为0表示成功,状态1表示失败,这通常会使不熟悉Unix的人感到困惑。 对于大多数人来说,如果它使用诸如对勾图标表示成功,而使用“ X”图标表示失败,则将更容易理解。

使用FontAwesome库获取选中标记和X图标。 就像从Bootstrap一样,只需从HTML <head>链接到库。 然后在JavaScript中修改循环以检查退出状态,如果状态为0则显示绿色,如果状态为其他,则显示红色X:


   
   
    for ( script in scriptStatuses ) {
      var fa_icon = scriptStatuses [ script ] ? 'fa-times' : 'fa-check' ;
      var icon_color = scriptStatuses [ script ] ? 'red' : 'green' ;
      $ ( '#status-table' ) . append (
        '<tr><td>' + script + '</td><td><i class="fa ' + fa_icon + '" style="color: ' + icon_color + '"></i></td></tr>'
      ) ;
    }

测试一下。 输入电子邮件地址,点击运行,然后…

Exit codes reported with icons

美丽! 有用!

另外的选择

多么富有成效的一天! 您构建了一个使工作的重要部分自动化的应用程序。 唯一的缺点是您必须维护云实例,前端JavaScript和后端Python代码。

但是,如果您没有一整天的时间花在自动化或不想永远维护它们呢? 系统管理员必须使所有板块保持旋转,处理紧急请求,并应对越来越多的高优先级票务积压。 但是您可能可以在星期五下午偷偷进行30分钟的流程改进。 那段时间您能取得什么成就?

如果这是90年代中期,则可以在30分钟内在Visual Basic中构建某些东西。 但是您正在尝试构建一个Web应用程序,而不是桌面应用程序。 幸运的是,这里有帮助:您可以使用Anvil (一种基于开放源代码软件构建的服务)来使用Python编写应用程序-这次只需30分钟:

Designing a project using Anvil

全面披露:Anvil是一项商业服务-尽管我们在本文中所做的一切都可以免费获得! 您可以在Anvil博客上找到有关构建此项目的分步指南

无论您走的是前进的道路-自行完成或使用诸如Anvil之类的工具,我们都希望您继续使所有事情自动化。 您要自动化哪种流程? 发表评论以激发您的系统管理员。

翻译自: https://opensource.com/article/19/9/web-apps-sysadmins

idea自动构建web项目

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值