Ansible源码学习(一)

news2025/2/23 13:32:31

一、背景说明

基于Ansible1.1源码学习

二、目录结构

ansible核心目录

ansible
├─bin    # 入口命令
│    ├─ansible
│    ├─ansible-doc
│    ├─ansible-playbook
│    ├─ansible-pull
├─lib   # 核心代码
│  └─ansible
│      ├─callback_plugins   # 回调插件
│      ├─inventory
│      │  └─vars_plugins    # 参数
│      ├─playbook           # 剧本
│      ├─runner
│      │  ├─action_plugins
│      │  ├─connection_plugins
│      │  ├─filter_plugins
│      │  └─lookup_plugins
│      └─utils
├─library    # ansible内置模块

三、核心代码

1. ansible获取ansible.cfg的函数

lib/ansible/constants.py

def load_config_file():
    p = ConfigParser.ConfigParser()
    path1 = os.path.expanduser(os.environ.get('ANSIBLE_CONFIG', "~/.ansible.cfg")) # 配置
    path2 = os.getcwd() + "/ansible.cfg" # 命令行传入
    path3 = "/etc/ansible/ansible.cfg"  # 默认路径

    if os.path.exists(path1):
        p.read(path1)
    elif os.path.exists(path2):
        p.read(path2)
    elif os.path.exists(path3):
        p.read(path3)
    else:
        return None
    return p

2. 插件加载函数

主要功能有两个:

  • 动态加载插件(py文件):imp.load_source
    • imp.load_source是python2的方法
    • python3的替代方法是: importlib.import_module
  • 通过字典_module_cache 缓存插件
    lib/ansible/utils/plugins.py
import os
import sys
import glob
import imp
import ansible.constants as C
from ansible import errors

_basedirs = []

def push_basedir(basedir):
    _basedirs.insert(0, basedir)

class PluginLoader(object):
    """PluginLoader loads plugins from the best source

    It searches for plugins by iterating through the combined list of
    play basedirs, configured paths, and the installed package directory.
    The first match is used.
    """
    def __init__(self, class_name, package, config, subdir, aliases={}):
        """Create a new PluginLoader"""
        self.class_name = class_name
        self.package = package
        self.config = config
        self.subdir = subdir
        self.aliases = aliases
        self._module_cache = {}
        self._extra_dirs = []

    def _get_package_path(self):
        """Gets the path of a Python package"""
        if not self.package:
            return []
        if not hasattr(self, 'package_path'):
            m = __import__(self.package)
            parts = self.package.split('.')[1:]
            self.package_path = os.path.join(os.path.dirname(m.__file__), *parts)
        return [self.package_path]

    def _get_paths(self):
        """Return a list of paths to search for plugins in

        The list is searched in order."""
        ret = []
        ret += self._extra_dirs
        for basedir in _basedirs:
            fullpath = os.path.join(basedir, self.subdir)
            if fullpath not in ret:
                ret.append(fullpath)
        ret += self.config.split(os.pathsep)
        ret += self._get_package_path()
        return ret

    def add_directory(self, directory, with_subdir=False):
        """Adds an additional directory to the search path"""
        if directory is not None:
            if with_subdir:
                directory = os.path.join(directory, self.subdir)
            self._extra_dirs.append(directory)

    def print_paths(self):
        """Returns a string suitable for printing of the search path"""
        # Uses a list to get the order right
        ret = []
        for i in self._get_paths():
            if i not in ret:
                ret.append(i)
        return os.pathsep.join(ret)

    def find_plugin(self, name):
        """Find a plugin named name"""
        suffix = ".py"
        if not self.class_name:
            suffix = ""
        for i in self._get_paths():
            path = os.path.join(i, "%s%s" % (name, suffix))
            if os.path.exists(path):
                return path
        return None

    def has_plugin(self, name):
        """Checks if a plugin named name exists"""
        return self.find_plugin(name) is not None
    __contains__ = has_plugin

    def get(self, name, *args, **kwargs):
        if name in self.aliases:
            name = self.aliases[name]
        path = self.find_plugin(name)
        if path is None:
            return None
        if path not in self._module_cache:
            self._module_cache[path] = imp.load_source('.'.join([self.package, name]), path)
        return getattr(self._module_cache[path], self.class_name)(*args, **kwargs)

    def all(self, *args, **kwargs):
        for i in self._get_paths():
            for path in glob.glob(os.path.join(i, "*.py")):
                name, ext = os.path.splitext(os.path.basename(path))
                if name.startswith("_"):
                    continue
                if path not in self._module_cache:
                    self._module_cache[path] = imp.load_source('.'.join([self.package, name]), path)
                yield getattr(self._module_cache[path], self.class_name)(*args, **kwargs)

action_loader     = PluginLoader('ActionModule',   'ansible.runner.action_plugins',     C.DEFAULT_ACTION_PLUGIN_PATH,     'action_plugins')
callback_loader   = PluginLoader('CallbackModule', 'ansible.callback_plugins',          C.DEFAULT_CALLBACK_PLUGIN_PATH,   'callback_plugins')
connection_loader = PluginLoader('Connection',     'ansible.runner.connection_plugins', C.DEFAULT_CONNECTION_PLUGIN_PATH, 'connection_plugins', aliases={'paramiko': 'paramiko_ssh'})
module_finder     = PluginLoader('',               '',                                  C.DEFAULT_MODULE_PATH,            'library')
lookup_loader     = PluginLoader('LookupModule',   'ansible.runner.lookup_plugins',     C.DEFAULT_LOOKUP_PLUGIN_PATH,     'lookup_plugins')
vars_loader       = PluginLoader('VarsModule',     'ansible.inventory.vars_plugins',    C.DEFAULT_VARS_PLUGIN_PATH,       'vars_plugins')
filter_loader     = PluginLoader('FilterModule',   'ansible.runner.filter_plugins',     C.DEFAULT_FILTER_PLUGIN_PATH,     'filter_plugins')

四、Ansible命令执行流程

在这里插入图片描述

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

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

相关文章

Netty核心技术六--Netty核心模块组件

1. Bootstrap、ServerBootstrap Bootstrap 意思是引导,一个 Netty 应用通常由一个Bootstrap 开始,主要作用是配置整个 Netty 程序,串联各个组件,Netty 中 Bootstrap 类是客户端程序的启动引导类,ServerBootstrap 是服…

【Linux】天天直接IO?我说停停,不如试试文件缓冲区

系列文章 收录于【Linux】文件系统 专栏 关于文件描述符与文件重定向的相关内容可以移步 文件描述符与重定向操作。 可以到 浅谈文件原理与操作 了解文件操作的系统接口。 目录 系列文章 揭秘C库文件结构体 文件缓冲区 为什么需要文件缓冲区 刷新机制 内核文件缓冲区…

java基础(多线程)-共享资源并发问题以及synchronized解决方案

一、共享资源带来的问题 class ThreadProblem{static int counter 0;public static void testThread(){Thread t1 new Thread(()-> {for (int i 0; i < 5000; i) {counter;}},"t1");Thread t2 new Thread(()-> {for (int i 0; i < 5000; i) {count…

【VMD-LSTM】变分模态分解-长短时记忆神经网络研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

主动降噪技术的运用及其展望---【其利天下技术】

降噪耳机想必大家是听说过的&#xff0c;那么什么是降噪耳机呢&#xff1f;降噪耳机的降噪是如何实现的呢&#xff1f; 在很多年前&#xff0c;我想大家肯定认为降噪耳机不就是做得比较帖耳&#xff0c;尽量把声波能量隔离不让进入人耳吗&#xff1f;搞得这么神秘干吗呢&#…

猿辅导基于 EMR StarRocks 的 OLAP 演进之路

摘要&#xff1a;猿辅导大数据平台团队负责人申阳分享了猿辅导基于 StarRocks 的 OLAP 演进之路。主要包括以下几大部分&#xff1a; 数据需求产生OLAP 选型StarRocks 的优势业务场景和技术方案基础建设 Tips&#xff1a;点击「阅读原文」查看原文视频 1► 数据需求产生 猿辅导…

【Linux】进程间通信(1)——匿名管道

文章目录 前言进程间通信的目的进程间通信的发展进程间通信分类管道什么是管道&#xff1f;站在内核角度-管道本质匿名管道pipe函数管道的特点&#xff08;重要&#xff09;用fork来共享管道原理匿名管道的使用步骤管道的读写规则管道的四种场景 如何使用管道进行进程间通信&am…

【Vue3学习】Vuex 状态管理 store

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 安装 npm npm install vuexnext --saveyarn npm install vuexnext --save基本使用 1&#xff09;创建…

Kubernetes初认识

系列文章目录 文章目录 系列文章目录一、Kubernetes初认识1.k8s的特性2.K8S架构3.Kubernetes工作流程 二、K8S创建Pod流程1.详细版2.简单版 总结 一、Kubernetes初认识 1.k8s的特性 弹性伸缩&#xff1a;使用命令、UI或者基于CPU使用情况自动快速扩容和缩容应用程序实例&…

磁盘调度算法及其应用

导读&#xff1a; 磁盘调度是计算机系统中的重要问题之一。在多个进程同时访问磁盘时&#xff0c;合理的磁盘调度算法可以优化磁盘访问顺序&#xff0c;提高系统性能。本文将介绍磁盘调度算法的基本思想&#xff0c;并通过一个实验来模拟不同调度算法的运行过程。 正文&#…

如何翻译 Markdown 文件?-2-几种商业及开源解决方案介绍

背景 近期在搭建英文博客-<e-whisper.com>, 需要对现有的所有中文 Markdown 翻译为英文。 需求如下&#xff1a; 将 Markdown 文件从中文 (zh-CN) 翻译为英文 (en)翻译后要保留 Markdown 的完整格式部分 Markdown block 不需要翻译&#xff0c;如&#xff1a;front-ma…

电脑蓝屏问题

如何使用DISM命令行工具修复Windows 10映像 - 系统极客 (sysgeek.cn) 电脑每周基本都会出现一次蓝屏问题&#xff1a;THREAD_STUCK_IN_DEVICE_DRIVER 售后重装系统&#xff0c;换主板&#xff0c;换硬盘都没有用&#xff0c;实在是人麻了 不知道有没有用&#xff0c;先记录一…

“边玩边赚”的区块链游戏发展前景和趋势

2008年&#xff0c;一个真实的故事。 大学期间&#xff0c;睡在我下铺的兄弟没日没夜地玩一款电脑游戏——《热血江湖》&#xff0c;期末考试和考研都没能阻止他。而最终&#xff0c;是游戏里的一把枪让他改邪归正。因为他把那件装备卖给了一个北京人&#xff0c;价格高达3000…

IT专业相关介绍【活动】

IT专业相关介绍【活动】 前言IT专业相关介绍一、IT专业的就业前景和发展趋势二、了解IT专业的分类和方向三、你对本专业的看法和感想四、本专业对人能力素养的要求五、建议和思考六、计算机思维能力测试 最后 前言 2023-6-17 10:00:29 以下内容源自《【活动】》 仅供学习交流…

Spring-kafka的消费者模型和实现原理

在使用Spring-kafka时,一般都是通过使用@KafkaListener注解的方法来实现消息监听和消费。今天写一下基于这个注解实现的消费端模型和实现的原理。 Kafka消费模型 我们在使用@KafkaListener注解实现消费者时消费者模型是这样的: 每个@KafkaListener注解对应有一个Concurren…

python窗口程序button事件处理

import tkinter as tk def add_counter(): #增加计数print("add....")def zero_counter(): #归零计数print("zero....")#窗口的属性&#xff08;大小&#xff0c;&#xff09; root tk.Tk() root.geometry("400x200200200") root.title(&q…

亚马逊云科技中国峰会:深度学习Amazon DeepRacer

序言 Amazon DeepRacer是什么&#xff1f; Amazon DeepRacer是亚马逊推出的一款基于深度学习和强化学习技术的自主驾驶模拟赛车平台。它提供了一个云端仿真环境和一个物理赛车模型&#xff0c;让用户可以通过编写代码和训练模型来控制赛车的行驶&#xff0c;从而学习和应用深…

【LeetCode】HOT 100(14)

题单介绍&#xff1a; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与数据结构的新手和想要在短时间内高效提升的人&#xff0c;熟练掌握这 100 道题&#xff0c;你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

音视频开发Level0: 入门级20~25k的工作

今天给大家分享一个音视频开发领域&#xff0c;入门级别的工作&#xff0c;要求不高。 主要做什么呢&#xff0c;行车记录仪&#xff0c;运动相机&#xff0c;各种拍摄器材包括医疗领域的喉镜啊&#xff0c;等等。 这种产品&#xff0c;招人的公司深圳最多&#xff0c;因为深…

Mac 多版本jdk安装与切换

macOS上可以安装多个版本的jdk&#xff0c;方法如下&#xff1a; 1.下载jdk 在Oracle官网上下载不同版本的jdk&#xff1a; JDK下载 知乎 - 安全中心 下载Java11版本链接 jdk11​www.oracle.com/java/technologies/javase-jdk11-downloads.html 2.安装jdk 运行此安装包&…