mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
commit
5a8ba39dd7
@ -407,6 +407,7 @@ execution modules
|
||||
supervisord
|
||||
suse_apache
|
||||
svn
|
||||
swarm
|
||||
swift
|
||||
sysbench
|
||||
sysfs
|
||||
|
6
doc/ref/modules/all/salt.modules.swarm.rst
Normal file
6
doc/ref/modules/all/salt.modules.swarm.rst
Normal file
@ -0,0 +1,6 @@
|
||||
=====================
|
||||
salt.modules.swarm
|
||||
=====================
|
||||
|
||||
.. automodule:: salt.modules.swarm
|
||||
:memebers:
|
6
doc/ref/returners/all/salt.returners.telegram_return.rst
Normal file
6
doc/ref/returners/all/salt.returners.telegram_return.rst
Normal file
@ -0,0 +1,6 @@
|
||||
==============================
|
||||
salt.returners.telegram_return
|
||||
==============================
|
||||
|
||||
.. automodule:: salt.returners.telegram_return
|
||||
:members:
|
414
salt/modules/swarm.py
Normal file
414
salt/modules/swarm.py
Normal file
@ -0,0 +1,414 @@
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Docker Swarm Module using Docker's Python SDK
|
||||
=============================================
|
||||
|
||||
:codeauthor: Tyler Jones <jonestyler806@gmail.com>
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
The Docker Swarm Module is used to manage and create Docker Swarms.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
- Docker installed on the host
|
||||
- Docker python sdk >= 2.5.1
|
||||
|
||||
Docker Python SDK
|
||||
-----------------
|
||||
pip install -U docker
|
||||
|
||||
More information: https://docker-py.readthedocs.io/en/stable/
|
||||
"""
|
||||
# Import python libraries
|
||||
from __future__ import absolute_import
|
||||
import json
|
||||
|
||||
try:
|
||||
import docker
|
||||
HAS_DOCKER = True
|
||||
except ImportError:
|
||||
HAS_DOCKER = False
|
||||
|
||||
__virtualname__ = 'swarm'
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Load this module if the docker python module is installed
|
||||
'''
|
||||
if HAS_DOCKER:
|
||||
return __virtualname__
|
||||
return False, 'The swarm module failed to load: Docker python module is not avaialble.'
|
||||
|
||||
|
||||
def __init__(self):
|
||||
__context__['client'] = docker.from_env()
|
||||
__context__['server_name'] = __grains__['id']
|
||||
|
||||
|
||||
def swarm_tokens():
|
||||
'''
|
||||
Get the Docker Swarm Manager or Worker join tokens
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' swarm.swarm_tokens
|
||||
'''
|
||||
client = docker.APIClient(base_url='unix://var/run/docker.sock')
|
||||
service = client.inspect_swarm()
|
||||
return service['JoinTokens']
|
||||
|
||||
|
||||
def swarm_init(advertise_addr=str,
|
||||
listen_addr=int,
|
||||
force_new_cluster=bool):
|
||||
'''
|
||||
Initalize Docker on Minion as a Swarm Manager
|
||||
|
||||
advertise_addr
|
||||
The ip of the manager
|
||||
|
||||
listen_addr
|
||||
Listen address used for inter-manager communication,
|
||||
as well as determining the networking interface used
|
||||
for the VXLAN Tunnel Endpoint (VTEP).
|
||||
This can either be an address/port combination in
|
||||
the form 192.168.1.1:4567,
|
||||
or an interface followed by a port number,
|
||||
like eth0:4567
|
||||
|
||||
force_new_cluster
|
||||
Force a new cluster if True is passed
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' swarm.swarm_init advertise_addr='192.168.50.10' listen_addr='0.0.0.0' force_new_cluster=False
|
||||
'''
|
||||
try:
|
||||
salt_return = {}
|
||||
__context__['client'].swarm.init(advertise_addr,
|
||||
listen_addr,
|
||||
force_new_cluster)
|
||||
output = 'Docker swarm has been Initalized on '+ __context__['server_name'] + ' and the worker/manager Join token is below'
|
||||
salt_return.update({'Comment': output,
|
||||
'Tokens': swarm_tokens()})
|
||||
except TypeError:
|
||||
salt_return = {}
|
||||
salt_return.update({'Error': 'Please make sure your passing advertise_addr, listen_addr and force_new_cluster correctly.'})
|
||||
return salt_return
|
||||
|
||||
|
||||
def joinswarm(remote_addr=int,
|
||||
listen_addr=int,
|
||||
token=str):
|
||||
'''
|
||||
Join a Swarm Worker to the cluster
|
||||
|
||||
remote_addr
|
||||
The manager node you want to connect to for the swarm
|
||||
|
||||
listen_addr
|
||||
Listen address used for inter-manager communication if the node gets promoted to manager,
|
||||
as well as determining the networking interface used for the VXLAN Tunnel Endpoint (VTEP)
|
||||
|
||||
token
|
||||
Either the manager join token or the worker join token.
|
||||
You can get the worker or manager token via `salt '*' swarm.swarm_tokens`
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' swarm.joinswarm remote_addr=192.168.50.10 listen_addr='0.0.0.0' token='SWMTKN-1-64tux2g0701r84ofq93zppcih0pe081akq45owe9ts61f30x4t-06trjugdu7x2z47j938s54il'
|
||||
'''
|
||||
try:
|
||||
salt_return = {}
|
||||
__context__['client'].swarm.join(remote_addrs=[remote_addr],
|
||||
listen_addr=listen_addr,
|
||||
join_token=token)
|
||||
output = __context__['server_name'] + ' has joined the Swarm'
|
||||
salt_return.update({'Comment': output, 'Manager_Addr': remote_addr})
|
||||
except TypeError:
|
||||
salt_return = {}
|
||||
salt_return.update({'Error': 'Please make sure this minion is not part of a swarm and your passing remote_addr, listen_addr and token correctly.'})
|
||||
return salt_return
|
||||
|
||||
|
||||
def leave_swarm(force=bool):
|
||||
'''
|
||||
Force the minion to leave the swarm
|
||||
|
||||
force
|
||||
Will force the minion/worker/manager to leave the swarm
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' swarm.leave_swarm force=False
|
||||
'''
|
||||
salt_return = {}
|
||||
__context__['client'].swarm.leave(force=force)
|
||||
output = __context__['server_name'] + ' has left the swarm'
|
||||
salt_return.update({'Comment': output})
|
||||
return salt_return
|
||||
|
||||
|
||||
def service_create(image=str,
|
||||
name=str,
|
||||
command=str,
|
||||
hostname=str,
|
||||
replicas=int,
|
||||
target_port=int,
|
||||
published_port=int):
|
||||
'''
|
||||
Create Docker Swarm Service Create
|
||||
|
||||
image
|
||||
The docker image
|
||||
|
||||
name
|
||||
Is the service name
|
||||
|
||||
command
|
||||
The docker command to run in the container at launch
|
||||
|
||||
hostname
|
||||
The hostname of the containers
|
||||
|
||||
replicas
|
||||
How many replicas you want running in the swarm
|
||||
|
||||
target_port
|
||||
The target port on the container
|
||||
|
||||
published_port
|
||||
port thats published on the host/os
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
salt '*' swarm.service_create image=httpd name=Test_Service command=None hostname=salthttpd replicas=6 target_port=80 published_port=80
|
||||
'''
|
||||
try:
|
||||
salt_return = {}
|
||||
replica_mode = docker.types.ServiceMode('replicated', replicas=replicas)
|
||||
ports = docker.types.EndpointSpec(ports={target_port: published_port})
|
||||
__context__['client'].services.create(name=name,
|
||||
image=image,
|
||||
command=command,
|
||||
mode=replica_mode,
|
||||
endpoint_spec=ports)
|
||||
echoback = __context__['server_name'] + ' has a Docker Swarm Service running named ' + name
|
||||
salt_return.update({'Info': echoback,
|
||||
'Minion': __context__['server_name'],
|
||||
'Name': name,
|
||||
'Image': image,
|
||||
'Command': command,
|
||||
'Hostname': hostname,
|
||||
'Replicas': replicas,
|
||||
'Target_Port': target_port,
|
||||
'Published_Port': published_port})
|
||||
except TypeError:
|
||||
salt_return = {}
|
||||
salt_return.update({'Error': 'Please make sure your passing arguments correctly [image, name, command, hostname, replicas, target_port and published_port]'})
|
||||
return salt_return
|
||||
|
||||
|
||||
def swarm_service_info(service_name=str):
|
||||
'''
|
||||
Swarm Service Information
|
||||
|
||||
service_name
|
||||
The name of the service that you want information on about the service
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
salt '*' swarm.swarm_service_info service_name=Test_Service
|
||||
'''
|
||||
try:
|
||||
salt_return = {}
|
||||
client = docker.APIClient(base_url='unix://var/run/docker.sock')
|
||||
service = client.inspect_service(service=service_name)
|
||||
getdata = json.dumps(service)
|
||||
dump = json.loads(getdata)
|
||||
version = dump['Version']['Index']
|
||||
name = dump['Spec']['Name']
|
||||
network_mode = dump['Spec']['EndpointSpec']['Mode']
|
||||
ports = dump['Spec']['EndpointSpec']['Ports']
|
||||
swarm_id = dump['ID']
|
||||
create_date = dump['CreatedAt']
|
||||
update_date = dump['UpdatedAt']
|
||||
labels = dump['Spec']['Labels']
|
||||
replicas = dump['Spec']['Mode']['Replicated']['Replicas']
|
||||
network = dump['Endpoint']['VirtualIPs']
|
||||
image = dump['Spec']['TaskTemplate']['ContainerSpec']['Image']
|
||||
for items in ports:
|
||||
published_port = items['PublishedPort']
|
||||
target_port = items['TargetPort']
|
||||
published_mode = items['PublishMode']
|
||||
protocol = items['Protocol']
|
||||
salt_return.update({'Service Name': name,
|
||||
'Replicas': replicas,
|
||||
'Service ID': swarm_id,
|
||||
'Network': network,
|
||||
'Network Mode': network_mode,
|
||||
'Creation Date': create_date,
|
||||
'Update Date': update_date,
|
||||
'Published Port': published_port,
|
||||
'Target Port': target_port,
|
||||
'Published Mode': published_mode,
|
||||
'Protocol': protocol,
|
||||
'Docker Image': image,
|
||||
'Minion Id': __context__['server_name'],
|
||||
'Version': version})
|
||||
except TypeError:
|
||||
salt_return = {}
|
||||
salt_return.update({'Error': 'service_name arg is missing?'})
|
||||
return salt_return
|
||||
|
||||
|
||||
def remove_service(service=str):
|
||||
'''
|
||||
Remove Swarm Service
|
||||
|
||||
service
|
||||
The name of the service
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
salt '*' swarm.remove_service service=Test_Service
|
||||
'''
|
||||
try:
|
||||
salt_return = {}
|
||||
client = docker.APIClient(base_url='unix://var/run/docker.sock')
|
||||
service = client.remove_service(service)
|
||||
salt_return.update({'Service Deleted': service,
|
||||
'Minion ID': __context__['server_name']})
|
||||
except TypeError:
|
||||
salt_return = {}
|
||||
salt_return.update({'Error': 'service arg is missing?'})
|
||||
return salt_return
|
||||
|
||||
|
||||
def node_ls(server=str):
|
||||
'''
|
||||
Displays Information about Swarm Nodes with passing in the server
|
||||
|
||||
server
|
||||
The minion/server name
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
salt '*' swarm.node_ls server=minion1
|
||||
'''
|
||||
try:
|
||||
salt_return = {}
|
||||
client = docker.APIClient(base_url='unix://var/run/docker.sock')
|
||||
service = client.nodes(filters=({'name': server}))
|
||||
getdata = json.dumps(service)
|
||||
dump = json.loads(getdata)
|
||||
for items in dump:
|
||||
docker_version = items['Description']['Engine']['EngineVersion']
|
||||
platform = items['Description']['Platform']
|
||||
hostnames = items['Description']['Hostname']
|
||||
ids = items['ID']
|
||||
role = items['Spec']['Role']
|
||||
availability = items['Spec']['Availability']
|
||||
status = items['Status']
|
||||
Version = items['Version']['Index']
|
||||
salt_return.update({'Docker Version': docker_version,
|
||||
'Platform': platform,
|
||||
'Hostname': hostnames,
|
||||
'ID': ids,
|
||||
'Roles': role,
|
||||
'Availability': availability,
|
||||
'Status': status,
|
||||
'Version': Version})
|
||||
except TypeError:
|
||||
salt_return = {}
|
||||
salt_return.update({'Error': 'The server arg is missing or you not targeting a Manager node?'})
|
||||
return salt_return
|
||||
|
||||
|
||||
def remove_node(node_id=str, force=bool):
|
||||
'''
|
||||
Remove a node from a swarm and the target needs to be a swarm manager
|
||||
|
||||
node_id
|
||||
The node id from the return of swarm.node_ls
|
||||
|
||||
force
|
||||
Forcefully remove the node/minion from the service
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
salt '*' swarm.remove_node node_id=z4gjbe9rwmqahc2a91snvolm5 force=false
|
||||
'''
|
||||
client = docker.APIClient(base_url='unix://var/run/docker.sock')
|
||||
try:
|
||||
if force == 'True':
|
||||
service = client.remove_node(node_id, force=True)
|
||||
return service
|
||||
else:
|
||||
service = client.remove_node(node_id, force=False)
|
||||
return service
|
||||
except TypeError:
|
||||
salt_return = {}
|
||||
salt_return.update({'Error': 'Is the node_id and/or force=True/False missing?'})
|
||||
return salt_return
|
||||
|
||||
|
||||
def update_node(availability=str,
|
||||
node_name=str,
|
||||
role=str,
|
||||
node_id=str,
|
||||
version=int):
|
||||
'''
|
||||
Updates docker swarm nodes/needs to target a manager node/minion
|
||||
|
||||
availability
|
||||
Drain or Active
|
||||
|
||||
node_name
|
||||
minion/node
|
||||
|
||||
role
|
||||
role of manager or worker
|
||||
|
||||
node_id
|
||||
The Id and that can be obtained via swarm.node_ls
|
||||
|
||||
version
|
||||
Is obtained by swarm.node_ls
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
salt '*' docker_util.update_node availability=drain node_name=minion2 role=worker node_id=3k9x7t8m4pel9c0nqr3iajnzp version=19
|
||||
'''
|
||||
client = docker.APIClient(base_url='unix://var/run/docker.sock')
|
||||
try:
|
||||
salt_return = {}
|
||||
node_spec = {'Availability': availability,
|
||||
'Name': node_name,
|
||||
'Role': role}
|
||||
client.update_node(node_id=node_id,
|
||||
version=version,
|
||||
node_spec=node_spec)
|
||||
salt_return.update({'Node Information': node_spec})
|
||||
except TypeError:
|
||||
salt_return = {}
|
||||
salt_return.update({'Error': 'Make sure all args are passed [availability, node_name, role, node_id, version]'})
|
||||
return salt_return
|
Loading…
Reference in New Issue
Block a user