Stay Hungry,Stay Foolish!

Ansible与Python API

Ansible

https://www.ansible.com/

自动化运维的最流行的工具。

Automation for everyone

Simplify work. Break down silos. Speed transformation.
All with an enterprise automation platform.

 

Simple, agentless IT automation that anyone can use

Ansible is a universal language, unraveling the mystery of how work gets done. Turn tough tasks into repeatable playbooks. Roll out enterprise-wide protocols with the push of a button.

 

中文:

https://ansible-tran.readthedocs.io/en/latest/index.html

 

原理

https://www.ansible.com/overview/how-ansible-works

以SSH作为传输通道,推送模块到远程机器, 然后执行此模块,反馈执行结果。

无任何代理agent。

EFFICIENT ARCHITECTURE

Ansible works by connecting to your nodes and pushing out small programs, called "Ansible modules" to them. These programs are written to be resource models of the desired state of the system. Ansible then executes these modules (over SSH by default), and removes them when finished.

Your library of modules can reside on any machine, and there are no servers, daemons, or databases required. Typically you'll work with your favorite terminal program, a text editor, and probably a version control system to keep track of changes to your content.

 

运行

https://www.ansible.com/overview/how-ansible-works

THE BASICS: USING ANSIBLE FOR AD HOC PARALLEL TASK EXECUTION

Once you have an instance available, you can talk to it right away, without any additional setup:

ansible all -m ping 
ansible foo.example.com -m yum -a "name=httpd state=installed"
ansible foo.example.com -a "/usr/sbin/reboot"

PLAYBOOKS: A SIMPLE+POWERFUL AUTOMATION LANGUAGE

Playbooks can finely orchestrate multiple slices of your infrastructure topology, with very detailed control over how many machines to tackle at a time.  This is where Ansible starts to get most interesting.

---
- yum: name={{contact.item}} state=installed
with_items:
- app_server
- acme_software


- service: name=app_server state=running enabled=yes


- template: src=/opt/code/templates/foo.j2 dest=/etc/foo.conf
notify: 
- restart app server

      使用如下命令运行  ansible-playbook yaml/httpd.yaml

 

更多playbook例子

https://github.com/ansible/ansible-examples

模块

https://docs.ansible.com/ansible/latest/modules/modules_by_category.html?extIdCarryOver=true&sc_cid=701f2000001OH7YAAW

命令行模块

https://docs.ansible.com/ansible/latest/modules/list_of_commands_modules.html

 

Python API

此API不是正规的API,仅仅是内部的API,可随版本不做兼容性考虑的改变。官方更加推荐 ansible tower,使用 rest api调用。

Ad-hoc

https://docs.ansible.com/ansible/latest/dev_guide/developing_api.html#python-api-2-0

#!/usr/bin/env python

import json
import shutil
from ansible.module_utils.common.collections import ImmutableDict
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
from ansible import context
import ansible.constants as C

class ResultCallback(CallbackBase):
    """A sample callback plugin used for performing an action as results come in

    If you want to collect all results into a single object for processing at
    the end of the execution, look into utilizing the ``json`` callback plugin
    or writing your own custom callback plugin
    """
    def v2_runner_on_ok(self, result, **kwargs):
        """Print a json representation of the result

        This method could store the result in an instance attribute for retrieval later
        """
        host = result._host
        print(json.dumps({host.name: result._result}, indent=4))

# since the API is constructed for CLI it expects certain options to always be set in the context object
context.CLIARGS = ImmutableDict(connection='local', module_path=['/to/mymodules'], forks=10, become=None,
                                become_method=None, become_user=None, check=False, diff=False)

# initialize needed objects
loader = DataLoader() # Takes care of finding and reading yaml, json and ini files
passwords = dict(vault_pass='secret')

# Instantiate our ResultCallback for handling results as they come in. Ansible expects this to be one of its main display outlets
results_callback = ResultCallback()

# create inventory, use path to host config file as source or hosts in a comma separated string
inventory = InventoryManager(loader=loader, sources='localhost,')

# variable manager takes care of merging all the different sources to give you a unified view of variables available in each context
variable_manager = VariableManager(loader=loader, inventory=inventory)

# create data structure that represents our play, including tasks, this is basically what our YAML loader does internally.
play_source =  dict(
        name = "Ansible Play",
        hosts = 'localhost',
        gather_facts = 'no',
        tasks = [
            dict(action=dict(module='shell', args='ls'), register='shell_out'),
            dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
         ]
    )

# Create play object, playbook objects use .load instead of init or new methods,
# this will also automatically create the task objects from the info provided in play_source
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

# Run it - instantiate task queue manager, which takes care of forking and setting up all objects to iterate over host list and tasks
tqm = None
try:
    tqm = TaskQueueManager(
              inventory=inventory,
              variable_manager=variable_manager,
              loader=loader,
              passwords=passwords,
              stdout_callback=results_callback,  # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
          )
    result = tqm.run(play) # most interesting data for a play is actually sent to the callback's methods
finally:
    # we always need to cleanup child procs and the structures we use to communicate with them
    if tqm is not None:
        tqm.cleanup()

    # Remove ansible tmpdir
    shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)

https://ansible-docs.readthedocs.io/zh/stable-2.0/rst/developing_api.html

playbook API

https://gist.github.com/viper233/69dfe7943b076f0d79db

#!/usr/bin/env python
# stolen from http://stackoverflow.com/questions/27590039/running-ansible-playbook-using-python-api

import os
import sys
from collections import namedtuple

from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.inventory import Inventory
from ansible.executor.playbook_executor import PlaybookExecutor

variable_manager = VariableManager()
loader = DataLoader()

inventory = Inventory(loader=loader, variable_manager=variable_manager,  host_list='/tmp/hosts')
playbook_path = '/tmp/ls.yml'

if not os.path.exists(playbook_path):
    print '[INFO] The playbook does not exist'
    sys.exit()

Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check'])

options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='local', module_path=None, forks=100, remote_user='stephen', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=False, become_method=None, become_user='root', verbosity=None, check=False)

variable_manager.extra_vars = {'hosts': 'localhost'} # This can accomodate various other command line arguments.`

passwords = {}

pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords)

results = pbex.run()

 

中文参考:

https://www.cnblogs.com/franknihao/p/9009110.html 两者都有

https://www.cnblogs.com/wanstack/p/8820889.html  playbook

https://www.jianshu.com/p/62b6d2325648  ad-hoc

http://www.iceyao.com.cn/2017/08/31/Ansible-API%E4%BD%BF%E7%94%A8/

 

posted @ 2020-03-03 12:03  lightsong  阅读(1048)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel