ansible-api分析(VariableManager变量)

news2025/1/8 15:31:44

一. 简述:

ansible是一个非常强大的工具,可以支持多种类型(字符,数字,列表,字典等)的变量。除了有大量的内置变量及fact变量,也可以通过多种方式进行变量自定义 。不同方式定义的变量,优先级也不太一样,之前有写过变量定义的说明,这里,从在使用api的过程中说明下。

二. VariableManager变量详解与使用案例

如果了解/使用过python 2.0版本以上的同学, 应该不会陌生以下几个类:

from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager 
from ansible.inventory import Inventory
from ansible.playbook.play import Play 
from ansible.executor.task_queue_manager import TaskQueueManager  
from ansible.plugins.callback import CallbackBase    

  其中VariableManager是用来存储各类的变量信息的。大家都知道,ansible可以分别通过yaml配置文件中的var,命令行的方式进行变量定义,hosts文件,也可以通过register(task内部专递),交互式的定义。 其实,还可以在一些比较特殊的场景进行变量定义。比如,我们动态生成hosts时(inventory),也可以定义。当然,在走api时,也可以通过这里要说的,VariableManager模块定义。

案例 (抛砖引玉): 

    通常情况下,我们可能会把变量定义在hosts文件,或者var下, 但在有些特殊的环境下,其实并不能满足我们的需求。比如,我司有aws,ali,ten等多个云运营商,同时,我们还会使用不同的系统版本(如centos6、fedora7)在在这个环境系下,我们不希望在初始化时,不同的商家/版本,使用不同的初始化脚本(playbook )【如果单独使用,意味着我们需要维护至少6个,三个运营商的提供环境是有差异性的, 当然,我们也考虑过基于某一个运营商的系统,打镜像,然后上传至其他运行商,实现环境统一的情况,但我们不能保证,这样操作会不会跟云平台能够完全契合】。所以,对于这种环境,我们需要设计一个统一的操作script,动态获取系统所属版本,所在运营商。include对应的配合文件,进行初始化工作。

结构如下:

# tree roles/ -d
initial_system.yaml 
roles/
├── initial_system_6
│   ├── files
│   ├── handlers
│   ├── tasks
│   │   ├── disk_initial.yaml
│   │   ├── file_copy.yaml
│   │   ├── jenkins_node.yaml
│   │   ├── main_ten.yaml
│   │   ├── main_ali.yaml
│   │   ├── main_aws.yaml
│   │   ├── main.yaml
│   │   ├── mysql_master.yaml
│   │   ├── mysql_slave.yaml
│   │   ├── nginx.yaml
│   │   ├── nodejs.yaml
│   │   ├── package_install.yaml
│   │   ├── py35.yaml
│   │   └── tomcat.yaml
│   ├── templates
│   └── vars
├── initial_system_7
│   ├── files
│   ├── handlers
│   ├── tasks
│   │   ├── disk_initial.yaml
│   │   ├── file_copy.yaml
│   │   ├── jenkins_node.yaml
│   │   ├── main_ten.yaml
│   │   ├── main_ali.yaml
│   │   ├── main_aws.yaml
│   │   ├── main.yaml
│   │   ├── mysql_master.yaml
│   │   ├── mysql_slave.yaml
│   │   ├── nginx.yaml
│   │   ├── nodejs.yaml
│   │   ├── package_install.yaml
│   │   ├── py35.yaml
│   │   └── tomcat.yaml
│   ├── templates
│   └── vars

如上图,我需要根据系统版本号,include对应的系统版本role(initial_system_6/7)。然后加载对应的task/main.yaml, 再根据获取的idc/运营商,加载不同的配置文件(main_aws.yaml)

我的playbook主配置内容如下:

# cat initial_system.yaml 
---
- hosts: "{{ host_name }}"
  remote_user: ansible
  become: yes
  serial: 5
  gather_facts: no
  roles:
      - initial_system_{{ system_versions }}

在这种情况下,我们是不能通过hosts/(inventory)来定义system_versions(系统版本)变量的,因为它在执行时roles时,还未获取到对应的变量, 这种情况下,如果不走api(源码入手),我们只能通过命令(ansible-playbook -e)的方式进行传递。 由于我们采用了api, 所以,我们可以通过上文中的VariableManager模块进行变量定义。

代码片段如下:

。。。。。。。。。。。。。。。。
class vipkidplayexecutor(PlaybookExecutor):

    def __init__(self,playbooks,inventory,variable_manager,loader,options,passwords,stdout_callback=None):
        self._playbooks = playbooks
        self._inventory = inventory
        self._variable_manager = variable_manager
        self._loader = loader
        self._options = options
        self.passwords = passwords
        self._unreachable_hosts = dict()

        if options.listhosts or options.listtasks or options.listtags or options.syntax:
            self._tqm = None
        else:
            self._tqm = TaskQueueManager(inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=self.passwords, stdout_callback=stdout_callback)

        check_for_controlpersist(C.ANSIBLE_SSH_EXECUTABLE)

class Playbookjob(object):

    def __init__(self,playbooks,host_list,host_name,support_service=[],ssh_user='ansiblle',passwords=None,forks=5):
        self.playbooks = playbooks
        self.host_list = host_list
        self.ssh_user = ssh_user
        self.passwords = dict(vault_pass=passwords)
        self.forks = forks

        self.host_variable = {'host_name':host_name,'support_service':support_service}

        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars =  dict(data_obtain(host_name),**self.host_variable)
        print(self.variable_manager.extra_vars)
        self.loader = DataLoader()

        self.Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user','remote_user', 'check', 'sudo_user', 'sudo','listhosts','listtasks','listtags','syntax'])
        self.options = self.Options(connection='smart', module_path=None, forks=self.forks, become=True, become_method='sudo', become_user='root',remote_user=self.ssh_user, check=False,sudo_user=None,sudo='yes',listhosts=None,listtasks=None,listtags=None,syntax=None)

        self.results_callback = CallbackModule()
        #host_list produce
        inev_data = open(self.host_list,'r').read()
        inev_file = '#!/usr/bin/python\nhost_info={"all":{"hosts":%s}}\n%s' % (host_name.split(','),inev_data)

        self.hostsFile = NamedTemporaryFile(delete=False)
        self.hostsFile.write(inev_file)
        self.hostsFile.close()
        self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.hostsFile.name)

#        print('-----%s' %self.host_list)
#        self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.host_list)

        self.variable_manager.set_inventory(self.inventory)

    def run(self):
        playbook_control = vipkidplayexecutor(
            playbooks = self.playbooks,
            inventory = self.inventory,
            variable_manager = self.variable_manager,
            loader = self.loader,
            options = self.options,
            passwords = self.passwords,
            stdout_callback = self.results_callback
        )
        playbook_control.run()

。。。。。。。。。。。。。。。。

先定义类self.variable_manager = VariableManager()

然后添加变量脚本传入变量: {'host_name':host_name,'support_service':support_service}

然后将变量加载至variable_manager的extra_vars方法,然后交给api(vipkidPlaybookExecutor)操作。

存储的变量(extra_vars)其实就是一个字典(dict), 代码中引入了变量和data_obtain方法的结果,可解析为:

{'host_name': 'l-ansible-initial1.ops.prod.aws.dm', 'system_versions': 6, 'b': 'c', 'support_service': ['tomcat','nginx']}

传入要初始化的主机(host_name),系统版本(system_versions),部署的服务(tomcat,nginx)。

然后通过TaskQueueManager将变量传递到Task。

 感兴趣或有相关需求的同学,可以根据实际情况适配。

 ----------------------------------------------------------------------------------------------

深耕运维行业多年,擅长linux、容器云原生、运维自动化等方面。
承接各类运维环境部署、方案设计/实施、服务代运维工作,欢迎沟通交流 !

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2273289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2025年PMP考试最新报名通知

经PMI和中国国际人才交流基金会研究决定,中国大陆地区2025年第一期PMI认证考试定于3月15日举办。在基金会网站报名参加本次PMI认证考试的考生须认真阅读下文,知悉考试安排及注意事项,并遵守考试有关规定。 一、时间安排 (一&#…

Mysql--基础篇--数据类型(整数,浮点数,日期,枚举,二进制,空间类型等)

MySQL提供了多种数据类型,用于定义表中列的数据格式。选择合适的数据类型不仅可以提高查询性能,还能确保数据的完整性和准确性。 一、数值类型 数值类型用于存储整数、浮点数和定点数。根据精度和范围的不同,数值类型可以分为以下几类&…

1-Transformer算法解读

目录 一.RNN与Transfrmer 二.word2vec 三.自注意力机制 四.辅助向量Q/K/V 五.计算过程 六.整体架构​编辑 七.Bert 一.RNN与Transfrmer RNN(循环神经网络)和Transformer都是深度学习中用于处理序列数据的模型,但它们在结构和性能上有显著的区别。以下是它们的一些…

Java Web开发进阶——Spring Boot与Spring Data JPA

Spring Data JPA 是 Spring 提供的一种面向数据访问的持久化框架,它简化了 JPA 的实现,为开发者提供了一种快速操作数据库的方式。在结合 Spring Boot 使用时,开发者能够快速完成数据库访问层的开发。 1. 介绍Spring Data JPA 1.1 什么是Spr…

【计算机操作系统:一、绪论】

第1章 绪论 1.1 操作系统在计算机系统中的地位 1.1.1 存储程序式计算机的结构和特点 存储程序式计算机(Stored Program Computer)是现代计算机的基础,其概念源于冯诺依曼(John von Neumann)提出的模型。这种计算机架…

如何查看服务器上的MySQL/Redis等系统服务状态和列表

如果呢你知道系统服务名称,要看状态很简单: systemctl status server-name 比如 systemctl status nginxsystemctl status redis # 等 这是一个nginx的示例: 那问题是 当你不知道服务名称时该怎么办。举个例子,比如mysql在启动…

安科瑞Acrel-1000DP分布式光伏监控系统在浙江安吉成3234.465kWp分布式光伏发电项目中的应用

摘 要:分布式光伏发电站是指将光伏发电组件安装在用户的建筑物屋顶、空地或其他适合的场地上,利用太阳能进行发电的一种可再生能源利用方式,与传统的大型集中式光伏电站相比,分布式光伏发电具有更灵活的布局、更低的建设成本和更高…

探索 Vue.js 的动态样式与交互:一个有趣的样式调整应用

修改日期备注2025.1.3初版 一、前言 今天和大家分享在 Vue.js 学习过程中开发的超酷的小应用。这个应用可以让我们通过一些简单的交互元素,如复选框、下拉菜单和输入框,来动态地改变页面上元素的样式哦 让我们一起深入了解一下这个项目的实现过程&…

大数据-268 实时数仓 - ODS层 将 Kafka 中的维度表写入 DIM

点一下关注吧!!!非常感谢!!持续更新!!! Java篇开始了! MyBatis 更新完毕目前开始更新 Spring,一起深入浅出! 目前已经更新到了: H…

把vue项目或者vue组件发布成npm包或者打包成lib库文件本地使用

将vue项目发布成npm库文件,第三方通过npm依赖安装使用;使用最近公司接了一个项目,这个项目需要集成到第三方页面,在第三方页面点击项目名称,页面变成我们的项目页面;要求以npm库文件提供给他们;…

Kafka为什么要放弃Zookeeper

1.Kafka简介 Apache Kafka最早是由Linkedin公司开发,后来捐献给了Apack基金会。 Kafka被官方定义为分布式流式处理平台,因为具备高吞吐、可持久化、可水平扩展等特性而被广泛使用。目前Kafka具体如下功能: 消息队列,Kafka具有系统解耦、流…

【JVM】总结篇-类的加载篇之 类的加载器 和ClassLoader分析

文章目录 类的加载器ClassLoader自定义类加载器双亲委派机制概念源码分析优势劣势如何打破Tomcat 沙箱安全机制JDK9 双亲委派机制变化 类的加载器 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader Thread.currentThread().getContextClassLoa…

java 转义 反斜杠 Unexpected internal error near index 1

代码: String str"a\\c"; //出现异常,Unexpected internal error near index 1 //System.out.println(str.replaceAll("\\", "c"));//以下三种都正确 System.out.println(str.replace(\\, c)); System.out.println(str.r…

el-table 实现纵向多级表头

为了实现上图效果,最开始打算用el-row、el-col去实现,但发现把表头和数据分成两大列时,数据太多时会导致所在格高度变高。但由于每一格数据肯定不一样,为保持高度样式一致,就需要我们手动去获取最高格的高度之后再设置…

2025最新版Visual Studio Code安装使用指南

2025最新版Visual Studio Code安装使用指南 Installation and Usage Guide for the Latest Visual Studio Code in 2024 By JacksonML 2025-1-7 1. Visual Studio Code背景 早在二十年前,通用的集成开发环境(Integrated Deveopment Environment, 简称…

Flutter 鸿蒙化 flutter和鸿蒙next混和渲染

前言导读 这一个节课我们讲一下PlatformView的是使用 我们在实战中有可能出现了在鸿蒙next只加载一部分Flutter的情况 我们今天就讲一下这种情况具体实现要使用到我们的PlatformView 效果图 具体实现: 一、Native侧 使用 DevEco Studio工具打开 platform_view_example\oho…

LabVIEW语言学习过程是什么?

学习LabVIEW语言的过程可以分为几个阶段,每个阶段的重点内容逐步加深,帮助你从入门到精通。以下是一个简洁的学习过程: ​ 1. 基础入门阶段 理解图形化编程:LabVIEW是一种图形化编程语言,与传统的文本编程语言不同&am…

Kubernetes Gateway API-4-TCPRoute和GRPCRoute

1 TCPRoute 目前 TCP routing 还处于实验阶段。 Gateway API 被设计为与多个协议一起工作,TCPRoute 就是这样一个允许管理TCP流量的路由。 在这个例子中,我们有一个 Gateway 资源和两个 TCPRoute 资源,它们按照以下规则分配流量&#xff1…

嵌入式SD/TF卡通用协议-SDIO协议

SD卡(SecureDigital MemoryCard)即:安全数码卡,它是在MMC的基础上发展而来,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒…

性能测试05|JMeter:分布式、报告、并发数计算、性能监控

目录 一、JMeter分布式 1、应用场景 2、原理 3、分布式相关注意事项 4、分布式配置与运行 二、JMeter报告 1、聚合报告 2、HTML报告 三、并发用户数(线程数)计算 四、JMeter下载第三方插件 五、性能监控 1、Concurrency Thread Group 线程组…