巨蟒python全栈开发-第11阶段 ansible_project3
今日大纲:
1.用户创建
2.前端优化
3.用户编辑
4.用户删除
5.ansible api介绍
1.用户创建
新建一个user_create.html的页面
<form class="form-horizontal" id="createForm" action="" method="post">{% csrf_token %} <div class="box-body"> {% for field in form %} <div class="form-group{% if field.errors %} has-error{% endif %}"> <label class="col-sm-2 control-label">{{ field.label }} {% if field.field.required %} <span class="text-red">*</span> {% endif %} </label> <div class="col-sm-9"> {{ field }} </div> <span class="help-block"> {% for error in field.errors %} {{ error }} {% endfor %} {{ field.help_text }} </span> </div> {% endfor %} <div class="box-footer text-center"> <button type="reset" class="btn btn-warning">清空</button> <button id="createBtn" type="button" class="btn btn-info">提交</button> <p class="text-center"><i id='iconWait'></i></p> </div> </div> </form> {% block js %} <script> $("#createBtn").on("click",function () { if ("{{ pk }}" == "0") { url="{% url 'createuser' %}" } else { url="{% url 'edituser' pk %}" } Net.post({ url:url, data:$("#createForm").serialize(), go:{% url 'userlist' %} }) }) </script> {% endblock %}
里边有一个"清空"按钮和"提交按钮",下边的id="iconWait"代表转圈的那个.
添加一个add-btn属性在userlist.html里边
下面,我们再创建一个py文件user_form.py
点代表当前文件夹下,两个点代表上层文件夹
下面,我们需要在web文件夹下面新建一个user.py文件
我们先导入上边的文件以及文件的类.
需要继续导入views.py中的render
下面,再写一个url在urls.py里边.
运行:
修改得到上边的内容.运行,依然是下图的样式的内容.
现在出现一个问题,点击"添加用户",弹不出来窗口.
将user_edit放到图示的位置.
将utils放到如图表示的位置.
下面是变化的一些文件内容.
urls.py
"""issue URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from web.views import * #*代表web中的views所有的 from web.user import * #*代表web中的user所有的 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', home,name='home'), url(r'^home2/', home2,name='home2'), url(r'^createuser/', create_user,name='createuser'), url(r'^edituser/(\d+)', create_user, name='edituser'), url(r'^login/', login, name='login'), url(r'^logout/', logout_view, name='logout'), url(r'^userlist/', userlist, name='userlist'), ]
home.html
{% extends 'master/base.html' %} {% block body %} <h1>da</h1> <div class="btn btn-sm btn-success create_btn" >创建</div> {% endblock %} {% block js %} <script> {#$("#user").addClass("active")#} {#$("#init").addClass("active")#} $("#menu_issue").addClass("active") $("#update").addClass("active") {#点击这个按钮执行下面的函数#} $(".create_btn").on("click",function () { ui.box({ remote:{% url 'home2' %} }) }) </script> {% endblock %}
home2.html
{#<h1>da</h1>#} <form action=""> </form> <div class="btn btn-sm btn-success create-btn" >创建home2</div> {#{% endblock %}#} <div><i class="wait"></i></div> {% block js %} <script> $("#user").addClass("active") $(".create-btn").on("click",function () { Net.post(//发送请求到后端 { "url":{% url 'home2' %}, "data":{"name":"alex","age":9000}, "go":{% url 'home' %}, } ) }) </script> {% endblock %}
login.html
{% load static %} <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>登录 - 代码发布系统</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <!-- Bootstrap 3.3.7 --> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}"> <!-- Font Awesome --> <link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.min.css' %}"> <!-- Ionicons --> <link rel="stylesheet" href="{% static 'plugins/Ionicons/css/ionicons.min.css' %}"> <!-- Theme style --> <link rel="stylesheet" href="{% static 'AdminLTE/css/AdminLTE.min.css' %}"> </head> <body class="hold-transition login-page" style="background-image: url({% static 'img/login_bg2.jpg' %}); background-repeat: no-repeat; background-size: 100%; "> <div class="login-box"> <div class="login-logo"> <a href=""><b style="color: #fff;">代码发布系统</b></a> </div> <!-- /.login-logo --> <div class="login-box-body"> <p class="login-box-msg">Sign in to start your session</p> <div class="text-red" style="text-align: center;"> </div> <form action="" method="post">{% csrf_token %} <div class="form-group has-feedback"> <input name="domain" type="hidden" class="form-control" placeholder="Domain" value="default"> <input name="email" type="text" class="form-control" placeholder="Username"> <span class="glyphicon glyphicon-envelope form-control-feedback"></span> </div> <div class="form-group has-feedback"> <input name="password" type="password" class="form-control" placeholder="Password"> <span class="glyphicon glyphicon-lock form-control-feedback"></span> </div> <p style="color: red;text-align: center">{{ error_msg }}</p> <div class="form-group has-feedback"> <button type="submit" class="btn btn-primary btn-block btn-flat">Sign In</button> </div> </form> </div> <!-- /.login-box-body --> </div> <!-- /.login-box --> </body> </html>
user_create.html
<form class="form-horizontal" id="createForm" action="" method="post">{% csrf_token %} <div class="box-body"> {% for field in form %} <div class="form-group{% if field.errors %} has-error{% endif %}"> <label class="col-sm-2 control-label">{{ field.label }} {% if field.field.required %} <span class="text-red">*</span> {% endif %} </label> <div class="col-sm-9"> {{ field }} </div> <span class="help-block"> {% for error in field.errors %} {{ error }} {% endfor %} {{ field.help_text }} </span> </div> {% endfor %} <div class="box-footer text-center"> <button type="reset" class="btn btn-warning">清空</button> <button id="createBtn" type="button" class="btn btn-info">提交</button> <p class="text-center"><i id='iconWait'></i></p> </div> </div> </form> {% block js %} <script> {#$("#createBtn").on("click",function () {#} {# if ("{{ pk }}" == "0") {#} {# url="{% url 'createuser ' %}"#} {# } else {#} {# url="{% url 'edituser' pk %}"#} {# }#} Net.post({ url:url, data:$("#createForm").serialize(), go:{% url 'userlist' %} }) // }) </script> {% endblock %}
user_edit.html
<form class="form-horizontal" id="createForm" action="" method="post">{% csrf_token %} <div class="box-body"> {% for field in form %} <div class="form-group{% if field.errors %} has-error{% endif %}"> <label class="col-sm-2 control-label">{{ field.label }} {% if field.field.required %} <span class="text-red">*</span> {% endif %} </label> <div class="col-sm-9"> {{ field }} </div> <span class="help-block"> {% for error in field.errors %} {{ error }} {% endfor %} {{ field.help_text }} </span> </div> {% endfor %} <div class="box-footer text-center"> <button type="reset" class="btn btn-warning">清空</button> <button id="createBtn" type="button" class="btn btn-info">提交</button> <p class="text-center"><i id='iconWait'></i></p> </div> </div> </form> {% block js %} <script> $("#createBtn").on("click",function () { Net.post({ url:{% url 'edituser' pk %}, data:$("#createForm").serialize(), go:{% url 'userlist' %} }) }) </script> {% endblock %}
userlist.html
{% extends 'master/base.html' %} {% block body %} <div class="row"> <div class="col-xs-12"> <div class="box"> <div class="box-header"> {# <h3 class="box-title">Responsive Hover Table</h3>#} {# <button class="btn-sm btn-success create-btn">添加用户</button>#} <div class="btn btn-sm btn-success add-btn">添加用户</div> <div class="box-tools pull-right"> <form action="" method="get"> <div class="input-group input-group-sm" style="width: 150px;"> <input type="text" name="table_search" class="form-control pull-right" placeholder="Search"> <div class="input-group-btn"> <button type="submit" class="btn btn-default"><i class="fa fa-search"></i></button> </div> </div> </form> </div> </div> <!-- /.box-header --> <div class="box-body table-responsive no-padding"> <table class="table table-hover"> <tr> <th>序号</th> <th>用户名</th> <th>用户邮箱</th> <th>角色</th> <th>部门</th> <th>是否可用</th> <th>创建时间</th> <th>操作</th> </tr> {% for user in users %} <tr> <td>{{ forloop.counter }}</td> <td>{{ user.name }}</td> <td>{{ user.email }}</td> <td>{{ user.get_role_display }}</td> <td>{{ user.department|default:"" }}</td> <td>{{ user.get_is_unable_display }}</td> <td>{{ user.create_time|date:"Y-m-d H:i:s" }}</td> <td> <div class="btn btn-success btn-sm edit-btn" data-url="{% url 'edituser' user.pk %}">编辑 </div> <div class="btn btn-warning btn-sm del-btn" data-url="{% url 'deluser' user.pk %}"> 删除 </div> </td> </tr> {% endfor %} </table> </div> <!-- /.box-body --> </div> <div> <ul class="pagination pagination-sm no-margin pull-right"> {{ page_html|safe }} </ul> <!-- /.box --> </div> </div> </div> {% endblock %} {% block js %} <script> {#$(".add-btn").on("click", function () {#} {# ui.box({#} {# title: "新增用户", //上边显示的标题#} {# remote:{% url "createuser" %}#} {# })#} $("#user").addClass("active"); $(".add-btn").on("click", function () { ui.box({ title: "新增用户", remote: {% url 'createuser' %} }) }) $(".edit-btn").on("click", function () { ui.box({ title: "编辑用户", remote: $(this).attr("data-url") }) }) $(".del-btn").on("click", function () { var url=$(this).attr("data-url"); ui.confirm("你确认要删除这条记录吗?",function () { Net.get({ url:url, reload:true, }) }) }) </script> {% endblock %}
上班经过很长的调试才调整好,现在在服务器上访问
127.0.0.1:8000/home和
127.0.0.1:8000/userlist
原因是上边的views.py
运行:
点击"添加用户",得到下边的窗体内容.
我们打开上边的index.html文件.
得到上面的form的内容.下面是查看源码.
思考如何全部都加上form-control?
上边是循环加上form-control属性.
所有的input所有类属性form-control.
我们需要继承这个新的NewModelform.
这个时候,再次点击"添加用户",出现下面的界面:
注意这个地方设置一下size.
上边写size的目的是调整大小,可以直接写在源码中.
下面修改之后的内容.
修改源码在这里修改不过来,因此还是写在原来的位置,具体原因未知???
这个时候,我们再点击"提交",出不来结果.怎么处理?
首先在页面中添加一个点击事件.
再次刷新页面,
下面我们直接获取,通过serialize方法
在后端打印下获取到的POST.
运行,点击上边的"创建用户",点击提交,服务端得到下面的结果.
得到上边的内容,需要都写上serialize().
serialize() 方法通过序列化表单值,创建 URL 编码文本字符串。
点击提交,
服务端依然得不到数据.
因为上边是id=
所以,下面需要加上#
点击提交,得到上边csrf中间件.
上边中包括很多值.下边的后端也拿到了很多的值.
这个时候,我们添加成功之后,跳转到userlist页面.
上边需要导入的三个包
下面,我们再写一个在后端真正提交的一个操作,如何写呢?
这个时候,再次测试可能会出现上边的错误内容,需要加上userlist函数,进行处理.
我们得到上边的内容,需要添加上路由userlist.
可能出现上边的错误.上边显示"这个字段不能为空"
最后这个地方,我们需要return返回这个email的.
点击"提交",
然后返回,首页.
下面,我们需要添加一个pull-right类属性
通过上边循环出内容
forloop.counter 总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,
所以在第一次循环时 forloop.counter 将会被设置为1。
得到上边的内容.
可以看一下models选择内容.
下面需要分析上边的循环出来的写法?
修改一下userlist.html文件,如上图所示
上边的错误,是我们需要加上userlist路径,如下图所示
2.前端优化.
上图是修改之后的userlist函数.
打开上边的文件,查看加的位置.
页码位置
上图是传递过来的内容.
这个时候,右下角就有页码了.
看一下能不能用搜索,搜alex,可以搜索到下面的内容.
增加和查找已经写完了,下面开始写编辑和删除了.
添加上边的active.
上边就是修改模板,
将上边的这个传递的参数.
这个时候,我们就将上边的内容成功修改成了"用户列表"这个内容.也就是说我们通过后端传递到了前端的位置.
思考用户名如何传递到前端?
上边是我们导入的模块.
session可以传递user用户名,我们还有什么办法传递?除了密码不能传递.
我们登录的时候已经拿到了用户名字.上图的第28行,如何传递到前端?
先写一个login和logout函数和路由再说.
上边我们跳转到的是userlist界面
前端怎么写?
登录之后没有出现用户名???
想要传递参数,必须放在session里边才能传递.
上边的31行不可以,我们用下图所示的试一下,看一下能不能全部传递过去?
得到上图这样,不是一个序列化的对象.查询出来的是queryset,如何变成可序列化的对象?
又出现上边的问题.
下面,来一个新的方法,导入下面的这个模块
再次运行.
我们看到上边的内容成功登陆.名字出来了,
还有一种方法是重写中间件,中间件有5个方法,重写的是哪个?
在这里,我们就先将上边这条语句注释掉.
再在auth.py里边写一个类.
上边是重写的类.以及其中的方法,上边是用法.其中打印一下response
下面,我们需要在settings.py中加上一个内容
用上边的方法,我们就不能用render了.下图中的第13行从render,替换成TemplateResponse.
刷新上边的这个界面.服务端得到这个数据,也就是我们打印出服务端的auth中的response
TemplateResponse在什么地方用?在模板渲染的时候才能用.
重写这个方法,再次打印另一个内容.
再次刷新一下,
我们得到下面的值.
我们需要更新一下这个内容.
我们将上边的内容,都修改成user.
为了不重复,我们还是需要重新修改会account
修改后,我们得到上边的内容.注意上边要加逗号,只有登录之后才会有account.
左上角我们需要修改用户名.
在上图中修改成user.name
这样就成功修改完成了.
一种是写在session中,另一种是重写中间件.
3.用户编辑
下面,再说一下编辑
上边我们加上了data-url
修改用户如何写?
下面先单独写一个编辑用户的内容.
user_edit.html就是由user_create.html修改过来的
修改的位置,
上边是我们传递过来的pk值.
可能出现没有edituser这个路径.
edituser这里需要传递一个pk值
前端多个空格可能就会出错.
这个时候,点击编辑,可以弹出,对应的窗体.
attrs可以拿到值.也可以加上一定的属性.比如加上disabled属性.
后边什么都不加可以拿到这个值.
$this表示的是当前点击的对象.
下面,我们合并一下这个创建和编辑.
js里边不能做数据判断,一切数值计算都需要转换成字符串
服务端出现一个错误,
因为此时要有一个视图函数需要都修改成create_user.
注意,uswer.pk是一定获取不到的
上图中加上引号,url
一直报错出不来前端的弹窗里边的内容,原因是多写了一个空格.
出现上图的没有定义,问题是什么?同名函数,共用一个函数和共用一个界面html
编辑,不改上边的代码,出现上边的问题"邮箱已存在",应该如何操作?
原因是什么?form没有写对.
下面修改form
此时,我们再次提交错误重复的信息,会出现上边的内容.
上图显示,我们点击"编辑",不修改,"提交",报上边的错误
上图是原来的样子,下面是修改之后的样子.
添加相同的邮箱可能存在错误.如何解决呢?
上图中,邮箱已存在,我们需要进一步操作.上边这个已经成功解决了问题.
最开始,我们是按照上图的写法,写的.
如果一开始查找的一条数据,下图的邮箱,并且修改的数据和库里边查找的数据是一样的,代表这条数据邮箱没有改变.所以return回去.
我们先去表里查找这个邮箱.如果查不到,证明是一个没有的数据.
如果查找到一个值和目前的传递进来的数据是不一致的.需要告诉,可能这里边是有的.
else将所有的阶段了,所以下面的三行数据都是不需要的了.具体见下图.
user.count()==1代表查找到的是自己的那条记录.并且传递过来的值是不一样的
对instance的理解,
我们得到上边的instance不是None,因此self.instance=instance.
#17行,查到了1条记录,并且邮箱没有改变,
下面是删除的内容.
4.用户删除
上图是删除,界面的写法,看一下源码中的写法:
刷新浏览器界面,点击"删除"
上边是后端传递的信息
上图是url中的删除路由.
当我们点击"确认"的时候,this就相当于上边的弹窗.
因此这种写法是错误的,我们需要按照下图的写法,将含有this的这行代码写在下图的位置.
这个时候,就可以成功删除了,删除的同时需要刷新一下也就是reload:true
注意,不能将登陆的用户删除,否则会跳转到登录界面.
5.ansible api介绍,一些环境的搭建
下面,我们需要在linux环境中安装开发环境.
yum install -y python36-pip python36-devel #安装成功 yum install -y openssl-devel #安装成功 #下面这个安装失败,原因是需要安装成功ansible才能安装下面的成功 pip3 install ansible
(1)安装python3
#第一步,走到opt目录下 cd /opt #第二步.解决python编译安装所需的软件依赖 yum install gcc patch libffi-devel python-devel zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel -y #第三步:下载python3源码包 wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz ls #看下是否有压缩包 xz -d Python-3.6.7.tar.xz tar -xf Python-3.6.7.tar #解压缩,生成一个python源码文件夹 ls #第四步:进入python源码文件夹 cd Python-3.6.7 ls #查看一下文件夹内的内容 #第五步:进行编译安装,编译三部曲,源码编译的过程,下一步就是这些东西 (1)第一曲 ./configure --prefix=/opt/python36/ #当前文件夹下的configure #--prefix 参数解释:指定python36安装的位置,绿色代表可执行 #上边这条命令必须进入文件夹 Python-3.6.7 执行 #这样就会自动释放一些编译文件 #只要不出现error(错误信息)就可以了,出现warning(报警信息)不重要 #这个时候就会多了一些makefile文件 ls (2)第二曲 make (3)第三曲,此时就开始安装python3软件 make install #上边两部可以合成一步 #make && make install #代表执行完make就执行后边的make install命令 #上边安装速度可能会慢一些 #第六步.进入python36 #安装目录,检查bin目录 python #按Tab键,python3没有出来,原因是环境变量没有配置 cd /opt/ ls #我们看到最终安装完成的包python36 cd python36/ ls #我们对bin目录有兴趣,需要进入 cd bin ls #第七步,配置python3的环境变量 PATH #1.取出当前的path变量(环境变量) echo $PATH #取出当前的环境变量 #/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin pwd #查看当前目录 #2.填写python3的bin目录到PATH中 PATH="/opt/python36/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin" #3.讲环境变量,写入到全局配置文件/etc/profile vim /etc/profile i #插入 o #走到下一行 4.写入如下代码,在最底行写入如下配置 PATH="/opt/python36/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin" 5.读取配置文件,加载变量生效 source /etc/profile python #按Tab键,查看python内容 python3 #进入python3交互界面
(2)安装django,运行django
yum install tree
#1.安装django模块 pip3 install -i https://pypi.douban.com/simple django==1.11.18 #ctrl+C中断安装 #2.升级pip pip3 install --upgrade pip pip3 list #看一下pip3安装了什么 #3.通过命令创建django项目 #django-admin startproject crm #django-admin startapp app01 cd /opt/ ls django-admin startproject crm ls cd crm ls python3 manage.py runserver #直接这样写是有问题的 #中断 python3 manage.py runserver 0.0.0.0:8000 #依然存在问题 #访问192.168.34.133:8000这个网址,可以访问,但是这里访问不成功,原因是防火墙 iptables -L #查看防火墙的一些规则 4.关闭防火墙 iptables -F 再次运行下面的命令: python3 manage.py runserver 0.0.0.0:8000#依然存在问题可能 python3 manage.py runserver 192.168.34.133:9999 #不行再试一下这个命令 #访问地址 192.168.34.133:9999 #浏览器中报下面的错误信息 #Invalid HTTP_HOST header: '192.168.34.133:9999'. You may need to #add '192.168.34.133' to ALLOWED_HOSTS. #下面,我们需要中断代码 ls tree cd .. #回到上一级目录回到 /opt目录下面 ls tree crm #看一下crm的目录结构 cd crm/ vim crm/settings.py /ALLOW #快速找到,修改内容 ALLOWED_HOSTS = ["*"] python3 manage.py runserver 192.168.34.133:9999 #在crm目录下面,再次启动 #访问192.168.34.133:9999可以成功访问了. 192.168.34.133:9999 192.168.34.133:9999/admin #可以正常使用了.
需求,加上hello 视图"来了老弟!"
vi crm/urls.py yyp #命令是复制一行,退出,创建app01 #创建一个app01 django-admin startapp app01 ls tree #当前在crm目录下面 vi crm/urls.py #再次打开这个文件 from django.conf.urls import url from django.contrib import admin from app01 import views #修改的位置1 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^hello/', views.hello), #修改的位置2 ]
ls #在crm下面 vi app01/views.py 用空格键解决,
from django.shortcuts import render,HttpResponse #添加后边的HttpResponse def hello(request): #添加函数 return HttpResponse("来了老弟") Create your views here.
vi crm/settings.py #在settings.py中导入app01 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', #修改的位置 ] #linux端口范围0-65536.5000-10000 ls python3 manage.py runserver 192.168.34.133:8000 #访问下面的地址 http://192.168.34.133:8000/ #报错,也就是首页没有东西.大黄页,我们在公网上不能让别人知道我们的视图,需要隐藏视图 #思路:将setting.py里边的debug由true修改成false vi crm/settings.py DEBUG = False #目的,不能将视图函数暴露给别人 #再次运行下面的命令 python3 manage.py runserver 192.168.34.133:8000 #访问浏览器地址 192.168.34.133:8000 #这个时候就不会暴露了 http://192.168.34.133:8000/hello/ #这个时候可以看到内容了
安装成功django之后,我们再次安装一遍ansible
pip3 install ansible
#安装成功
这样,我们就将ansible模块和python3以及django安装成功了.
上图是centos7的写法,下图是centos6的写法
网关被.1是window机器占用,因此我们需要用,2
也可以在下图的网关设置中加上DNS.这样就可以加上一个静态IP地址了.
最后,我们还是只需要关注下面的三个信息.
下图是我自己的IP修改内容
下面看一下ansible的源码,
上边是AdHoc函数.
ansible -m 模块名 -a 参数
对应的是playbook函数
我们先执行一个命令
上边组织了一个"主机数据"
上边我们可以看到"ok","failed","unreachable","skipped",四个顶级的字典,ok,失败,不可达,跳过.
ok中,第一个ip地址,stdout表示输出,/root,pwd表示执行的命令
启动上边的两台机器,上图,在第1和第2条命令中间执行
第一条表示修改数据,得到下面的结果
如果修改成上图中,一个没有的命令"pd",
这个时候,就直接出来在failed里边了.
上图第二行的倒数部分显示,命令没有找到.
我们再写一台找不到主机的.
再次运行,看一下区别是什么?
一种是命令错误,另一种是端口不可达是找不到主机.
hostnane的作用是什么?
下面我们改成104
hostname代表的是key值.
上图是我们传递值到这个函数里边.
103行,判断是不是一个list,断言.
loader_class()
我们看到下图导入的这个包,ansible自带的一个方法,数据加载
这个时候又运行了下面的方法,
看一下这个变量管理类
然后,就初始化了下图的函数.
然后执行,下面的方法
循环主机数据,在列表中.
下面,就等于上图中的Host,点击77行的Host,我们得到下面的内容,
传递过来host_data,host_data循环这个列表中的每一个值.
端口默认是22,如果是22可以默认不写,具体见下图,
添加密码和秘钥文件.
如果没有vars,默认是一个空的字典,items(),然后组合了一下
playbook有一个变量的说法,
ansible自动2.0之后adhoc也会转换到playbook里边执行.
下图,是hostname出来的值104
没有组的话,我们需要在组的基础上添加信息.
注意ansible中有一个"组"的概念.
之前都是在init_host文件里边改的,现在我们只需要将IP地址组成一个虚拟的组.
然后将虚拟的组,给了CommandRunner,这个类继承自AdHocRunner这个类
再次看一下,AdHocRunner定义的内容,
上图就是我们自定义的回调函数.
21行表示的是命名元组,一系列参数的指定.forks表示的是并发
ansible -h #查看帮助信息,默认是5个,这里设置的是10个.
我们将拿到的值进行处理.执行init方法
也就是说,执行上图的C都满满的Runner,也就是执行init方法.也就是下图函数的init方法
先执行init,再执行CommandRunner,然后,我们再执行下图的函数
函数传递了三个参数,下面开始做判断,如果module有,并且不再选择的范围内,报错.如果不传,默认是module="shell"
也就是从test_runner.py传递过来的内容.
也就是说,上图的hosts,等于实例化的inventory,
动态生成上图的invent,然后得到所有的inventory
上图的hosts和name等于的值.然后再运行上图中的run,也就是父类的内容
也就是下面,我们传递进来的值,
上图是获取系统的变量,
第一个if语句,如果不是pattern,我们返回一个空的 {}
再看一下下图的信息
上图的callback信息.
看一下上图的tasks,tasks做的是下图的信息.
得到上图的信息.
我们将值统统加载到clean_tasks列表中,然后返回回去
下图是组装的一个字典
上边传递的值进行对应
得到上图的play,
上图是定义的回调函数以及password,上边是组成的组tqm
运行上图的位置
异常中什么都没有写,
这就是ansible走AdHoc走的一系列命令.
知道怎么用就行了,这只是官网上的一部分,修改了一点点
AdHoc和下面的command差不多
最后也是组成了上边的内容.
同样,运行了下面的run方法.
上边打开的文件,以及内容
上边的stdout对应的值是root,,命令是whoami
得到上边的内容.
上图是playbook组成一个列表,同样动态生成一个crm,playbookrunner
然后运行,下面的run方法,传递的是playbook_path参数,将path变成列表将值放在括号里边
然后,我们运行了下面的run().
得到上边的内容.也就是下面的vi a.yml
写的是下面的内容.
执行下面的yml文件.
运行一下报错,
再次打开,修改
得到下面的内容.
上边显示的错误是极其连接不上.上边是机器的状态是OK的,运行playbook,下面的一行显示的信息.
下面,我们拿到这个信息就可以进行判断了.
下面,我们再次写一个正常的主机和ip进行处理.
这个时候,我们再次运行.
上班的Gathering Facts, playbook的第一步是收集用户的信息,下图白色部分是一个大的列表.
tasks第一个是手机信息,createuser
我们看到了下图这个主机被创建了.
同样,我们可以传递变量,修改上边的这个playbook文件
传递下面的数据.
这个时候,我们再次执行
得到下图的name101
再看一下101IP中是否成功完成了创建账户alex101了.
注意,这个playbook的hosts需要协程all,需要哪个用就可以了,如果写成单个的机器需要正则匹配很麻烦,这里不多说.
用哪台机器,传递哪台机器就可以了.
6,特殊好用的工具在windows和linux上
得到上边的内容.
点击"Yes"
点击上图位置
我们得到了后端linux的目录,可以查看
点击右下角的OK
OK,