Merge branch 'develop' into boto_asg

This commit is contained in:
Nicole Thomas 2017-10-18 12:52:58 -04:00 committed by GitHub
commit 23deab2f4d
44 changed files with 1590 additions and 375 deletions

View File

@ -34,6 +34,7 @@ Full list of Salt Cloud modules
scaleway
softlayer
softlayer_hw
vagrant
virtualbox
vmware
vultrpy

View File

@ -0,0 +1,6 @@
=========================
salt.cloud.clouds.vagrant
=========================
.. automodule:: salt.cloud.clouds.vagrant
:members:

View File

@ -267,6 +267,7 @@ state modules
tuned
uptime
user
vagrant
vault
vbox_guest
victorops

View File

@ -0,0 +1,6 @@
===================
salt.states.vagrant
===================
.. automodule:: salt.states.vagrant
:members:

View File

@ -6,7 +6,7 @@ Introduced in Salt version ``2017.7.0`` it is now possible to run select states
in parallel. This is accomplished very easily by adding the ``parallel: True``
option to your state declaration:
.. code_block:: yaml
.. code-block:: yaml
nginx:
service.running:
@ -24,7 +24,7 @@ state to finish.
Given this example:
.. code_block:: yaml
.. code-block:: yaml
sleep 10:
cmd.run:
@ -74,16 +74,16 @@ also complete.
Things to be Careful of
=======================
Parallel States does not prevent you from creating parallel conflicts on your
Parallel States do not prevent you from creating parallel conflicts on your
system. This means that if you start multiple package installs using Salt then
the package manager will block or fail. If you attempt to manage the same file
with multiple states in parallel then the result can produce an unexpected
file.
Make sure that the states you choose to run in parallel do not conflict, or
else, like in and parallel programming environment, the outcome may not be
else, like in any parallel programming environment, the outcome may not be
what you expect. Doing things like just making all states run in parallel
will almost certinly result in unexpected behavior.
will almost certainly result in unexpected behavior.
With that said, running states in parallel should be safe the vast majority
of the time and the most likely culprit for unexpected behavior is running

View File

@ -540,6 +540,17 @@ machines which are already installed, but not Salted. For more information about
this driver and for configuration examples, please see the
:ref:`Gettting Started with Saltify <getting-started-with-saltify>` documentation.
.. _config_vagrant:
Vagrant
-------
The Vagrant driver is a new, experimental driver for controlling a VagrantBox
virtual machine, and installing Salt on it. The target host machine must be a
working salt minion, which is controlled via the salt master using salt-api.
For more information, see
:ref:`Getting Started With Vagrant <getting-started-with-vagrant>`.
Extending Profiles and Cloud Providers Configuration
====================================================

View File

@ -38,26 +38,30 @@ These are features that are available for almost every cloud host.
.. container:: scrollable
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
| |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | | |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+=======+=========+=========+======+
|Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|Full Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|Selective Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|List Sizes |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|List Images |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|List Locations |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|create |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|destroy |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
| |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify|Vagrant|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | | | |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+=======+=======+=========+=========+======+
|Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[1] |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|Full Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[1] |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|Selective Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[1] |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|List Sizes |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[2] |[2] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|List Images |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|List Locations |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[2] |[2] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|create |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|destroy |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[1] |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
[1] Yes, if salt-api is enabled.
[2] Always returns `{}`.
Actions
=======
@ -70,46 +74,46 @@ instance name to be passed in. For example:
.. container:: scrollable
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|Actions |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | | |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+=======+=========+=========+======+
|attach_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|create_attach_volumes |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|del_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|delvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|detach_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|disable_term_protect |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|enable_term_protect |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|keepvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_keypairs | | |Yes | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|rename |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|set_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_delvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_instance | | |Yes |Yes| | |Yes | |Yes | | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_term_protect | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|start |Yes | | |Yes| |Yes |Yes | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|stop |Yes | | |Yes| |Yes |Yes | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|take_action | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|Actions |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify&|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | Vagrant| |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+========+=========+=========+======+
|attach_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|create_attach_volumes |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|del_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|delvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|detach_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|disable_term_protect |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|enable_term_protect |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|keepvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_keypairs | | |Yes | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|rename |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|set_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_delvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_instance | | |Yes |Yes| | |Yes | |Yes | | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_term_protect | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|start |Yes | | |Yes| |Yes |Yes | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|stop |Yes | | |Yes| |Yes |Yes | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|take_action | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
Functions
=========
@ -122,81 +126,83 @@ require the name of the provider to be passed in. For example:
.. container:: scrollable
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|Functions |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | | |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+=======+=========+=========+======+
|block_device_mappings |Yes | | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|create_keypair | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|create_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|delete_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|delete_keypair | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|delete_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_image | | |Yes | | |Yes | | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_ip | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_key | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_keyid | | |Yes | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_keypair | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_networkid | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_node | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_password | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_size | | |Yes | | |Yes | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_spot_config | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_subnetid | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|iam_profile |Yes | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|import_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|key_list | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|keyname |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_availability_zones| | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_custom_images | | | | | | | | | | | |Yes | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_keys | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_nodes |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_nodes_full |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_nodes_select |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_vlans | | | | | | | | | | | |Yes |Yes | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|rackconnect | | | | | | | |Yes | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|reboot | | | |Yes| |Yes | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|reformat_node | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|securitygroup |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|securitygroupid | | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_image | | | |Yes| | | | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_keypair | | |Yes |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_volume | | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|Functions |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify&|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | Vagrant| |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+========+=========+=========+======+
|block_device_mappings |Yes | | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|create_keypair | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|create_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|delete_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|delete_keypair | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|delete_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_image | | |Yes | | |Yes | | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_ip | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_key | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_keyid | | |Yes | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_keypair | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_networkid | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_node | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_password | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_size | | |Yes | | |Yes | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_spot_config | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_subnetid | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|iam_profile |Yes | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|import_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|key_list | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|keyname |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_availability_zones| | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_custom_images | | | | | | | | | | | |Yes | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_keys | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_nodes |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_nodes_full |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_nodes_select |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_vlans | | | | | | | | | | | |Yes |Yes | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|rackconnect | | | | | | | |Yes | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|reboot | | | |Yes| |Yes | | | | |[1] | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|reformat_node | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|securitygroup |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|securitygroupid | | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_image | | | |Yes| | | | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_keypair | | |Yes |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_volume | | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
[1] Yes, if salt-api is enabled.

View File

@ -129,6 +129,7 @@ Cloud Provider Specifics
Getting Started With Scaleway <scaleway>
Getting Started With Saltify <saltify>
Getting Started With SoftLayer <softlayer>
Getting Started With Vagrant <vagrant>
Getting Started With Vexxhost <vexxhost>
Getting Started With Virtualbox <virtualbox>
Getting Started With VMware <vmware>

View File

@ -183,6 +183,8 @@ simple installation.
ssh_username: vagrant # a user name which has passwordless sudo
password: vagrant # on your target machine
provider: my_saltify_provider
shutdown_on_destroy: true # halt the target on "salt-cloud -d" command
.. code-block:: yaml

View File

@ -0,0 +1,268 @@
.. _getting-started-with-vagrant:
============================
Getting Started With Vagrant
============================
The Vagrant driver is a new, experimental driver for spinning up a VagrantBox
virtual machine, and installing Salt on it.
Dependencies
============
The Vagrant driver itself has no external dependencies.
The machine which will host the VagrantBox must be an already existing minion
of the cloud server's Salt master.
It must have Vagrant_ installed, and a Vagrant-compatible virtual machine engine,
such as VirtualBox_.
(Note: The Vagrant driver does not depend on the salt-cloud VirtualBox driver in any way.)
.. _Vagrant: https://www.vagrantup.com/
.. _VirtualBox: https://www.virtualbox.org/
\[Caution: The version of Vagrant packaged for ``apt install`` in Ubuntu 16.04 will not connect a bridged
network adapter correctly. Use a version downloaded directly from the web site.\]
Include the Vagrant guest editions plugin:
``vagrant plugin install vagrant-vbguest``.
Configuration
=============
Configuration of the client virtual machine (using VirtualBox, VMware, etc)
will be done by Vagrant as specified in the Vagrantfile on the host machine.
Salt-cloud will push the commands to install and provision a salt minion on
the virtual machine, so you need not (perhaps **should** not) provision salt
in your Vagrantfile, in most cases.
If, however, your cloud master cannot open an SSH connection to the child VM,
you may **need** to let Vagrant provision the VM with Salt, and use some other
method (such as passing a pillar dictionary to the VM) to pass the master's
IP address to the VM. The VM can then attempt to reach the salt master in the
usual way for non-cloud minions. Specify the profile configuration argument
as ``deploy: False`` to prevent the cloud master from trying.
.. code-block:: yaml
# Note: This example is for /etc/salt/cloud.providers file or any file in
# the /etc/salt/cloud.providers.d/ directory.
my-vagrant-config:
minion:
master: 111.222.333.444
provider: vagrant
Because the Vagrant driver needs a place to store the mapping between the
node name you use for Salt commands and the Vagrantfile which controls the VM,
you must configure your salt minion as a Salt smb server.
(See `host provisioning example`_ below.)
Profiles
========
Vagrant requires a profile to be configured for each machine that needs Salt
installed. The initial profile can be set up at ``/etc/salt/cloud.profiles``
or in the ``/etc/salt/cloud.profiles.d/`` directory.
Each profile requires a ``vagrantfile`` parameter. If the Vagrantfile has
definitions for `multiple machines`_ then you need a ``machine`` parameter,
.. _`multiple machines`: https://www.vagrantup.com/docs/multi-machine/
Salt-cloud uses SSH to provision the minion. There must be a routable path
from the cloud master to the VM. Usually, you will want to use
a bridged network adapter for SSH. The address may not be known until
DHCP assigns it. If ``ssh_host`` is not defined, and ``target_network``
is defined, the driver will attempt to read the address from the output
of an ``ifconfig`` command. Lacking either setting,
the driver will try to use the value Vagrant returns as its ``ssh_host``,
which will work only if the cloud master is running somewhere on the same host.
The ``target_network`` setting should be used
to identify the IP network your bridged adapter is expected to appear on.
Use CIDR notation, like ``target_network: '2001:DB8::/32'``
or ``target_network: '192.0.2.0/24'``.
Profile configuration example:
.. code-block:: yaml
# /etc/salt/cloud.profiles.d/vagrant.conf
vagrant-machine:
host: my-vhost # the Salt id of the virtual machine's host computer.
provider: my-vagrant-config
cwd: /srv/machines # the path to your Virtualbox file.
vagrant_runas: my-username # the username who defined the Vagrantbox on the host
# vagrant_up_timeout: 300 # (seconds) timeout for cmd.run of the "vagrant up" command
# vagrant_provider: '' # option for "vagrant up" like: "--provider vmware_fusion"
# ssh_host: None # "None" means try to find the routable IP address from "ifconfig"
# target_network: None # Expected CIDR address of your bridged network
# force_minion_config: false # Set "true" to re-purpose an existing VM
The machine can now be created and configured with the following command:
.. code-block:: bash
salt-cloud -p vagrant-machine my-id
This will create the machine specified by the cloud profile
``vagrant-machine``, and will give the machine the minion id of
``my-id``. If the cloud master is also the salt-master, its Salt
key will automatically be accepted on the master.
Once a salt-minion has been successfully installed on the instance, connectivity
to it can be verified with Salt:
.. code-block:: bash
salt my-id test.ping
.. _host provisioning example:
Provisioning a Vagrant cloud host (example)
===========================================
In order to query or control minions it created, each host
minion needs to track the Salt node names associated with
any guest virtual machines on it.
It does that using a Salt sdb database.
The Salt sdb is not configured by default. The following example shows a
simple installation.
This example assumes:
- you are on a large network using the 10.x.x.x IP address space
- your Salt master's Salt id is "bevymaster"
- it will also be your salt-cloud controller
- it is at hardware address 10.124.30.7
- it is running a recent Debian family Linux (raspbian)
- your workstation is a Salt minion of bevymaster
- your workstation's minion id is "my_laptop"
- VirtualBox has been installed on "my_laptop" (apt install is okay)
- Vagrant was installed from vagrantup.com. (not the 16.04 Ubuntu apt)
- "my_laptop" has done "vagrant plugin install vagrant-vbguest"
- the VM you want to start is on "my_laptop" at "/home/my_username/Vagrantfile"
.. code-block:: yaml
# file /etc/salt/minion.d/vagrant_sdb.conf on host computer "my_laptop"
# -- this sdb database is required by the Vagrant module --
vagrant_sdb_data: # The sdb database must have this name.
driver: sqlite3 # Let's use SQLite to store the data ...
database: /var/cache/salt/vagrant.sqlite # ... in this file ...
table: sdb # ... using this table name.
create_table: True # if not present
Remember to re-start your minion after changing its configuration files...
``sudo systemctl restart salt-minion``
.. code-block:: ruby
# -*- mode: ruby -*-
# file /home/my_username/Vagrantfile on host computer "my_laptop"
BEVY = "bevy1"
DOMAIN = BEVY + ".test" # .test is an ICANN reserved non-public TLD
# must supply a list of names to avoid Vagrant asking for interactive input
def get_good_ifc() # try to find a working Ubuntu network adapter name
addr_infos = Socket.getifaddrs
addr_infos.each do |info|
a = info.addr
if a and a.ip? and not a.ip_address.start_with?("127.")
return info.name
end
end
return "eth0" # fall back to an old reliable name
end
Vagrant.configure(2) do |config|
config.ssh.forward_agent = true # so you can use git ssh://...
# add a bridged network interface. (try to detect name, then guess MacOS names, too)
interface_guesses = [get_good_ifc(), 'en0: Ethernet', 'en1: Wi-Fi (AirPort)']
config.vm.network "public_network", bridge: interface_guesses
if ARGV[0] == "up"
puts "Trying bridge network using interfaces: #{interface_guesses}"
end
config.vm.provision "shell", inline: "ip address", run: "always" # make user feel good
# . . . . . . . . . . . . Define machine QUAIL1 . . . . . . . . . . . . . .
config.vm.define "quail1", primary: true do |quail_config|
quail_config.vm.box = "boxesio/xenial64-standard" # a public VMware & Virtualbox box
quail_config.vm.hostname = "quail1." + DOMAIN # supply a name in our bevy
quail_config.vm.provider "virtualbox" do |v|
v.memory = 1024 # limit memory for the virtual box
v.cpus = 1
v.linked_clone = true # make a soft copy of the base Vagrant box
v.customize ["modifyvm", :id, "--natnet1", "192.168.128.0/24"] # do not use 10.x network for NAT
end
end
end
.. code-block:: yaml
# file /etc/salt/cloud.profiles.d/my_vagrant_profiles.conf on bevymaster
q1:
host: my_laptop # the Salt id of your virtual machine host
machine: quail1 # a machine name in the Vagrantfile (if not primary)
vagrant_runas: my_username # owner of Vagrant box files on "my_laptop"
cwd: '/home/my_username' # the path (on "my_laptop") of the Vagrantfile
provider: my_vagrant_provider # name of entry in provider.conf file
target_network: '10.0.0.0/8' # VM external address will be somewhere here
.. code-block:: yaml
# file /etc/salt/cloud.providers.d/vagrant_provider.conf on bevymaster
my_vagrant_provider:
driver: vagrant
minion:
master: 10.124.30.7 # the hard address of the master
Create and use your new Salt minion
-----------------------------------
- Typing on the Salt master computer ``bevymaster``, tell it to create a new minion named ``v1`` using profile ``q1``...
.. code-block:: bash
sudo salt-cloud -p q1 v1
sudo salt v1 network.ip_addrs
[ you get a list of IP addresses, including the bridged one ]
- logged in to your laptop (or some other computer known to GitHub)...
\[NOTE:\] if you are using MacOS, you need to type ``ssh-add -K`` after each boot,
unless you use one of the methods in `this gist`_.
.. _this gist: https://github.com/jirsbek/SSH-keys-in-macOS-Sierra-keychain
.. code-block:: bash
ssh -A vagrant@< the bridged network address >
# [ or, if you are at /home/my_username/ on my_laptop ]
vagrant ssh quail1
- then typing on your new node "v1" (a.k.a. quail1.bevy1.test)...
.. code-block:: bash
password: vagrant
# [ stuff types out ... ]
ls -al /vagrant
# [ should be shared /home/my_username from my_laptop ]
# you can access other network facilities using the ssh authorization
# as recorded in your ~.ssh/ directory on my_laptop ...
sudo apt update
sudo apt install git
git clone ssh://git@github.com/yourID/your_project
# etc...

View File

@ -14,23 +14,33 @@ CVE-2017-14695 Directory traversal vulnerability in minion id validation in Salt
CVE-2017-14696 Remote Denial of Service with a specially crafted authentication request. Credit for discovering the security flaw goes to: Julian Brost (julian@0x4a42.net)
Extended changelog courtesy of Todd Stansell (https://github.com/tjstansell/salt-changelogs):
Known Issues
============
On 2017.7.2 when using salt-api and cherrypy version 5.6.0, issue `#43581`_ will occur when starting the salt-api service. We have patched the cherry-py packages for python-cherrypy-5.6.0-2 from repo.saltstack.com. If you are using python-cherrypy-5.6.0-1 please ensure to run `yum install python-cherrypy` to install the new patched version.
*Generated at: 2017-09-26T21:06:19Z*
Extended changelog courtesy of Todd Stansell (https://github.com/tjstansell/salt-changelogs):
Statistics:
*Generated at: 2017-10-02T21:10:14Z*
- Total Merges: **326**
- Total Issue references: **133**
- Total PR references: **389**
Statistics
==========
Changes:
- Total Merges: **328**
- Total Issue references: **134**
- Total PR references: **391**
Changes
=======
- **PR** `#43868`_: (*rallytime*) Back-port `#43847`_ to 2017.7.2
* Fix to module.run
- **PR** `#43756`_: (*gtmanfred*) split build and install for pkg osx
@ *2017-09-26T20:51:28Z*
* 88414d5 Merge pull request `#43756`_ from gtmanfred/2017.7.2
* f7df41f split build and install for pkg osx
- **PR** `#43585`_: (*rallytime*) Back-port `#43330`_ to 2017.7.2
@ *2017-09-19T17:33:34Z*
@ -3110,6 +3120,12 @@ Changes:
.. _`#480`: https://github.com/saltstack/salt/issues/480
.. _`#495`: https://github.com/saltstack/salt/issues/495
.. _`#43581`: https://github.com/saltstack/salt/issues/43581
.. _`#43756`: https://github.com/saltstack/salt/pull/43756
.. _`#43847`: https://github.com/saltstack/salt/pull/43847
.. _`#43868`: https://github.com/saltstack/salt/pull/43868
.. _`#475`: https://github.com/saltstack/salt/issues/475
.. _`#480`: https://github.com/saltstack/salt/issues/480
.. _`#495`: https://github.com/saltstack/salt/issues/495
.. _`bp-37424`: https://github.com/saltstack/salt/pull/37424
.. _`bp-39366`: https://github.com/saltstack/salt/pull/39366
.. _`bp-41543`: https://github.com/saltstack/salt/pull/41543

View File

@ -138,6 +138,56 @@ file. For example:
These commands will run in sequence **before** the bootstrap script is executed.
New salt-cloud Grains
=====================
When salt cloud creates a new minon, it will now add grain information
to the minion configuration file, identifying the resources originally used
to create it.
The generated grain information will appear similar to:
.. code-block:: yaml
grains:
salt-cloud:
driver: ec2
provider: my_ec2:ec2
profile: ec2-web
The generation of salt-cloud grains can be surpressed by the
option ``enable_cloud_grains: 'False'`` in the cloud configuration file.
Upgraded Saltify Driver
=======================
The salt-cloud Saltify driver is used to provision machines which
are not controlled by a dedicated cloud supervisor (such as typical hardware
machines) by pushing a salt-bootstrap command to them and accepting them on
the salt master. Creation of a node has been its only function and no other
salt-cloud commands were implemented.
With this upgrade, it can use the salt-api to provide advanced control,
such as rebooting a machine, querying it along with conventional cloud minions,
and, ultimately, disconnecting it from its master.
After disconnection from ("destroying" on) one master, a machine can be
re-purposed by connecting to ("creating" on) a subsequent master.
New Vagrant Driver
==================
The salt-cloud Vagrant driver brings virtual machines running in a limited
environment, such as a programmer's workstation, under salt-cloud control.
This can be useful for experimentation, instruction, or testing salt configurations.
Using salt-api on the master, and a salt-minion running on the host computer,
the Vagrant driver can create (``vagrant up``), restart (``vagrant reload``),
and destroy (``vagrant destroy``) VMs, as controlled by salt-cloud profiles
which designate a ``Vagrantfile`` on the host machine.
The master can be a very limited machine, such as a Raspberry Pi, or a small
VagrantBox VM.
New pillar/master_tops module called saltclass
----------------------------------------------

View File

@ -27,7 +27,7 @@ Installing Dependencies
=======================
Both pygit2_ and GitPython_ are supported Python interfaces to git. If
compatible versions of both are installed, pygit2_ will preferred. In these
compatible versions of both are installed, pygit2_ will be preferred. In these
cases, GitPython_ can be forced using the :conf_master:`gitfs_provider`
parameter in the master config file.

View File

@ -88,7 +88,8 @@ sudo $PKGRESOURCES/build_env.sh $PYVER
echo -n -e "\033]0;Build: Install Salt\007"
sudo rm -rf $SRCDIR/build
sudo rm -rf $SRCDIR/dist
sudo $PYTHON $SRCDIR/setup.py build -e "$PYTHON -E -s" install
sudo $PYTHON $SRCDIR/setup.py build -e "$PYTHON -E -s"
sudo $PYTHON $SRCDIR/setup.py install
############################################################################
# Build Package

View File

@ -1417,7 +1417,7 @@ class Cloud(object):
if name in vms:
prov = vms[name]['provider']
driv = vms[name]['driver']
msg = six.u('{0} already exists under {1}:{2}').format(
msg = u'{0} already exists under {1}:{2}'.format(
name, prov, driv
)
log.error(msg)

View File

@ -2080,6 +2080,7 @@ def attach_disk(name=None, kwargs=None, call=None):
disk_name = kwargs['disk_name']
mode = kwargs.get('mode', 'READ_WRITE').upper()
boot = kwargs.get('boot', False)
auto_delete = kwargs.get('auto_delete', False)
if boot and boot.lower() in ['true', 'yes', 'enabled']:
boot = True
else:
@ -2109,7 +2110,8 @@ def attach_disk(name=None, kwargs=None, call=None):
transport=__opts__['transport']
)
result = conn.attach_volume(node, disk, ex_mode=mode, ex_boot=boot)
result = conn.attach_volume(node, disk, ex_mode=mode, ex_boot=boot,
ex_auto_delete=auto_delete)
__utils__['cloud.fire_event'](
'event',
@ -2389,6 +2391,8 @@ def create_attach_volumes(name, kwargs, call=None):
'type': The disk type, either pd-standard or pd-ssd. Optional, defaults to pd-standard.
'image': An image to use for this new disk. Optional.
'snapshot': A snapshot to use for this new disk. Optional.
'auto_delete': An option(bool) to keep or remove the disk upon
instance deletion. Optional, defaults to False.
Volumes are attached in the order in which they are given, thus on a new
node the first volume will be /dev/sdb, the second /dev/sdc, and so on.
@ -2416,7 +2420,8 @@ def create_attach_volumes(name, kwargs, call=None):
'size': volume['size'],
'type': volume.get('type', 'pd-standard'),
'image': volume.get('image', None),
'snapshot': volume.get('snapshot', None)
'snapshot': volume.get('snapshot', None),
'auto_delete': volume.get('auto_delete', False)
}
create_disk(volume_dict, 'function')

View File

@ -0,0 +1,338 @@
# -*- coding: utf-8 -*-
'''
Vagrant Cloud Driver
====================
The Vagrant cloud is designed to "vagrant up" a virtual machine as a
Salt minion.
Use of this module requires some configuration in cloud profile and provider
files as described in the
:ref:`Gettting Started with Vagrant <getting-started-with-vagrant>` documentation.
.. versionadded:: Oxygen
'''
# Import python libs
from __future__ import absolute_import
import logging
import os
import tempfile
# Import salt libs
import salt.utils
import salt.config as config
import salt.client
import salt.ext.six as six
if six.PY3:
import ipaddress
else:
import salt.ext.ipaddress as ipaddress
from salt.exceptions import SaltCloudException, SaltCloudSystemExit
# Get logging started
log = logging.getLogger(__name__)
def __virtual__():
'''
Needs no special configuration
'''
return True
def avail_locations(call=None):
r'''
This function returns a list of locations available.
CLI Example:
.. code-block:: bash
salt-cloud --list-locations my-cloud-provider
# \[ vagrant will always returns an empty dictionary \]
'''
return {}
def avail_images(call=None):
'''This function returns a list of images available for this cloud provider.
vagrant will return a list of profiles.
salt-cloud --list-images my-cloud-provider
'''
vm_ = get_configured_provider()
return {'Profiles': [profile for profile in vm_['profiles']]}
def avail_sizes(call=None):
r'''
This function returns a list of sizes available for this cloud provider.
CLI Example:
.. code-block:: bash
salt-cloud --list-sizes my-cloud-provider
# \[ vagrant always returns an empty dictionary \]
'''
return {}
def list_nodes(call=None):
'''
List the nodes which have salt-cloud:driver:vagrant grains.
CLI Example:
.. code-block:: bash
salt-cloud -Q
'''
nodes = _list_nodes(call)
return _build_required_items(nodes)
def _build_required_items(nodes):
ret = {}
for name, grains in nodes.items():
if grains:
private_ips = []
public_ips = []
ips = grains['ipv4'] + grains['ipv6']
for adrs in ips:
ip_ = ipaddress.ip_address(adrs)
if not ip_.is_loopback:
if ip_.is_private:
private_ips.append(adrs)
else:
public_ips.append(adrs)
ret[name] = {
'id': grains['id'],
'image': grains['salt-cloud']['profile'],
'private_ips': private_ips,
'public_ips': public_ips,
'size': '',
'state': 'running'
}
return ret
def list_nodes_full(call=None):
'''
List the nodes, ask all 'vagrant' minions, return dict of grains (enhanced).
CLI Example:
.. code-block:: bash
salt-call -F
'''
ret = _list_nodes(call)
for key, grains in ret.items(): # clean up some hyperverbose grains -- everything is too much
try:
del grains['cpu_flags'], grains['disks'], grains['pythonpath'], grains['dns'], grains['gpus']
except KeyError:
pass # ignore absence of things we are eliminating
except TypeError:
del ret[key] # eliminate all reference to unexpected (None) values.
reqs = _build_required_items(ret)
for name in ret:
ret[name].update(reqs[name])
return ret
def _list_nodes(call=None):
'''
List the nodes, ask all 'vagrant' minions, return dict of grains.
'''
local = salt.client.LocalClient()
ret = local.cmd('salt-cloud:driver:vagrant', 'grains.items', '', tgt_type='grain')
return ret
def list_nodes_select(call=None):
'''
Return a list of the minions that have salt-cloud grains, with
select fields.
'''
return salt.utils.cloud.list_nodes_select(
list_nodes_full('function'), __opts__['query.selection'], call,
)
def show_instance(name, call=None):
'''
List the a single node, return dict of grains.
'''
local = salt.client.LocalClient()
ret = local.cmd(name, 'grains.items', '')
reqs = _build_required_items(ret)
ret[name].update(reqs[name])
return ret
def _get_my_info(name):
local = salt.client.LocalClient()
return local.cmd(name, 'grains.get', ['salt-cloud'])
def create(vm_):
'''
Provision a single machine
CLI Example:
.. code-block:: bash
salt-cloud -p my_profile new_node_1
'''
name = vm_['name']
machine = config.get_cloud_config_value(
'machine', vm_, __opts__, default='')
vm_['machine'] = machine
host = config.get_cloud_config_value(
'host', vm_, __opts__, default=NotImplemented)
vm_['cwd'] = config.get_cloud_config_value(
'cwd', vm_, __opts__, default='/')
vm_['runas'] = config.get_cloud_config_value(
'vagrant_runas', vm_, __opts__, default=os.getenv('SUDO_USER'))
vm_['timeout'] = config.get_cloud_config_value(
'vagrant_up_timeout', vm_, __opts__, default=300)
vm_['vagrant_provider'] = config.get_cloud_config_value(
'vagrant_provider', vm_, __opts__, default='')
vm_['grains'] = {'salt-cloud:vagrant': {'host': host, 'machine': machine}}
log.info('sending \'vagrant.init %s machine=%s\' command to %s', name, machine, host)
local = salt.client.LocalClient()
ret = local.cmd(host, 'vagrant.init', [name], kwarg={'vm': vm_, 'start': True})
log.info('response ==> %s', ret[host])
network_mask = config.get_cloud_config_value(
'network_mask', vm_, __opts__, default='')
if 'ssh_host' not in vm_:
ret = local.cmd(host,
'vagrant.get_ssh_config',
[name],
kwarg={'network_mask': network_mask,
'get_private_key': True})[host]
with tempfile.NamedTemporaryFile() as pks:
if 'private_key' not in vm_ and ret.get('private_key', False):
pks.write(ret['private_key'])
pks.flush()
log.debug('wrote private key to %s', pks.name)
vm_['key_filename'] = pks.name
if 'ssh_host' not in vm_:
vm_.setdefault('ssh_username', ret['ssh_username'])
if ret.get('ip_address'):
vm_['ssh_host'] = ret['ip_address']
else: # if probe failed or not used, use Vagrant's reported ssh info
vm_['ssh_host'] = ret['ssh_host']
vm_.setdefault('ssh_port', ret['ssh_port'])
log.info('Provisioning machine %s as node %s using ssh %s',
machine, name, vm_['ssh_host'])
ret = __utils__['cloud.bootstrap'](vm_, __opts__)
return ret
def get_configured_provider():
'''
Return the first configured instance.
'''
ret = config.is_provider_configured(
__opts__,
__active_provider_name__ or 'vagrant',
''
)
return ret
# noinspection PyTypeChecker
def destroy(name, call=None):
'''
Destroy a node.
CLI Example:
.. code-block:: bash
salt-cloud --destroy mymachine
'''
if call == 'function':
raise SaltCloudSystemExit(
'The destroy action must be called with -d, --destroy, '
'-a, or --action.'
)
opts = __opts__
__utils__['cloud.fire_event'](
'event',
'destroying instance',
'salt/cloud/{0}/destroying'.format(name),
args={'name': name},
sock_dir=opts['sock_dir'],
transport=opts['transport']
)
my_info = _get_my_info(name)
profile_name = my_info[name]['profile']
profile = opts['profiles'][profile_name]
host = profile['host']
local = salt.client.LocalClient()
ret = local.cmd(host, 'vagrant.destroy', [name])
if ret[host]:
__utils__['cloud.fire_event'](
'event',
'destroyed instance',
'salt/cloud/{0}/destroyed'.format(name),
args={'name': name},
sock_dir=opts['sock_dir'],
transport=opts['transport']
)
if opts.get('update_cachedir', False) is True:
__utils__['cloud.delete_minion_cachedir'](
name, __active_provider_name__.split(':')[0], opts)
return {'Destroyed': '{0} was destroyed.'.format(name)}
else:
return {'Error': 'Error destroying {}'.format(name)}
# noinspection PyTypeChecker
def reboot(name, call=None):
'''
Reboot a vagrant minion.
name
The name of the VM to reboot.
CLI Example:
.. code-block:: bash
salt-cloud -a reboot vm_name
'''
if call != 'action':
raise SaltCloudException(
'The reboot action must be called with -a or --action.'
)
my_info = _get_my_info(name)
profile_name = my_info[name]['profile']
profile = __opts__['profiles'][profile_name]
host = profile['host']
local = salt.client.LocalClient()
return local.cmd(host, 'vagrant.reboot', [name])

View File

@ -69,12 +69,11 @@ def init_git_pillar(opts):
for opts_dict in [x for x in opts.get('ext_pillar', [])]:
if 'git' in opts_dict:
try:
pillar = salt.utils.gitfs.GitPillar(opts)
pillar.init_remotes(
pillar = salt.utils.gitfs.GitPillar(
opts,
opts_dict['git'],
git_pillar.PER_REMOTE_OVERRIDES,
git_pillar.PER_REMOTE_ONLY
)
per_remote_overrides=git_pillar.PER_REMOTE_OVERRIDES,
per_remote_only=git_pillar.PER_REMOTE_ONLY)
ret.append(pillar)
except FileserverConfigError:
if opts.get('git_pillar_verify_config', True):

View File

@ -71,6 +71,15 @@ log = logging.getLogger(__name__)
__virtualname__ = 'git'
def _gitfs(init_remotes=True):
return salt.utils.gitfs.GitFS(
__opts__,
__opts__['gitfs_remotes'],
per_remote_overrides=PER_REMOTE_OVERRIDES,
per_remote_only=PER_REMOTE_ONLY,
init_remotes=init_remotes)
def __virtual__():
'''
Only load if the desired provider module is present and gitfs is enabled
@ -79,7 +88,7 @@ def __virtual__():
if __virtualname__ not in __opts__['fileserver_backend']:
return False
try:
salt.utils.gitfs.GitFS(__opts__)
_gitfs(init_remotes=False)
# Initialization of the GitFS object did not fail, so we know we have
# valid configuration syntax and that a valid provider was detected.
return __virtualname__
@ -92,18 +101,14 @@ def clear_cache():
'''
Completely clear gitfs cache
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
return gitfs.clear_cache()
return _gitfs(init_remotes=False).clear_cache()
def clear_lock(remote=None, lock_type='update'):
'''
Clear update.lk
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.clear_lock(remote=remote, lock_type=lock_type)
return _gitfs().clear_lock(remote=remote, lock_type=lock_type)
def lock(remote=None):
@ -114,30 +119,21 @@ def lock(remote=None):
information, or a pattern. If the latter, then remotes for which the URL
matches the pattern will be locked.
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.lock(remote=remote)
return _gitfs().lock(remote=remote)
def update():
'''
Execute a git fetch on all of the repos
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
gitfs.update()
_gitfs().update()
def envs(ignore_cache=False):
'''
Return a list of refs that can be used as environments
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.envs(ignore_cache=ignore_cache)
return _gitfs().envs(ignore_cache=ignore_cache)
def find_file(path, tgt_env='base', **kwargs): # pylint: disable=W0613
@ -145,10 +141,7 @@ def find_file(path, tgt_env='base', **kwargs): # pylint: disable=W0613
Find the first file to match the path and ref, read the file out of git
and send the path to the newly cached file
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.find_file(path, tgt_env=tgt_env, **kwargs)
return _gitfs().find_file(path, tgt_env=tgt_env, **kwargs)
def init():
@ -156,29 +149,21 @@ def init():
Initialize remotes. This is only used by the master's pre-flight checks,
and is not invoked by GitFS.
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
_gitfs()
def serve_file(load, fnd):
'''
Return a chunk from a file based on the data received
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.serve_file(load, fnd)
return _gitfs().serve_file(load, fnd)
def file_hash(load, fnd):
'''
Return a file hash, the hash type is set in the master config file
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.file_hash(load, fnd)
return _gitfs().file_hash(load, fnd)
def file_list(load):
@ -186,10 +171,7 @@ def file_list(load):
Return a list of all files on the file server in a specified
environment (specified as a key within the load dict).
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.file_list(load)
return _gitfs().file_list(load)
def file_list_emptydirs(load): # pylint: disable=W0613
@ -204,17 +186,11 @@ def dir_list(load):
'''
Return a list of all directories on the master
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.dir_list(load)
return _gitfs().dir_list(load)
def symlink_list(load):
'''
Return a dict of all symlinks based on a given path in the repo
'''
gitfs = salt.utils.gitfs.GitFS(__opts__)
gitfs.init_remotes(__opts__['gitfs_remotes'],
PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
return gitfs.symlink_list(load)
return _gitfs().symlink_list(load)

View File

@ -486,11 +486,11 @@ class Master(SMaster):
for repo in git_pillars:
new_opts[u'ext_pillar'] = [repo]
try:
git_pillar = salt.utils.gitfs.GitPillar(new_opts)
git_pillar.init_remotes(
git_pillar = salt.utils.gitfs.GitPillar(
new_opts,
repo[u'git'],
salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
salt.pillar.git_pillar.PER_REMOTE_ONLY)
per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY)
except FileserverConfigError as exc:
critical_errors.append(exc.strerror)
finally:

View File

@ -132,7 +132,7 @@ def version(*names, **kwargs):
return __salt__['pkg_resource.version'](*names, **kwargs)
def refresh_db(failhard=False):
def refresh_db(failhard=False, **kwargs): # pylint: disable=unused-argument
'''
Updates the opkg database to latest packages based upon repositories
@ -514,7 +514,7 @@ def purge(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument
return remove(name=name, pkgs=pkgs)
def upgrade(refresh=True):
def upgrade(refresh=True, **kwargs): # pylint: disable=unused-argument
'''
Upgrades all packages via ``opkg upgrade``
@ -803,7 +803,7 @@ def list_pkgs(versions_as_list=False, **kwargs):
return ret
def list_upgrades(refresh=True):
def list_upgrades(refresh=True, **kwargs): # pylint: disable=unused-argument
'''
List all available package upgrades.
@ -976,7 +976,7 @@ def info_installed(*names, **kwargs):
return ret
def upgrade_available(name):
def upgrade_available(name, **kwargs): # pylint: disable=unused-argument
'''
Check whether or not an upgrade is available for a given package
@ -989,7 +989,7 @@ def upgrade_available(name):
return latest_version(name) != ''
def version_cmp(pkg1, pkg2, ignore_epoch=False):
def version_cmp(pkg1, pkg2, ignore_epoch=False, **kwargs): # pylint: disable=unused-argument
'''
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
@ -1038,7 +1038,7 @@ def version_cmp(pkg1, pkg2, ignore_epoch=False):
return None
def list_repos():
def list_repos(**kwargs): # pylint: disable=unused-argument
'''
Lists all repos on /etc/opkg/*.conf
@ -1075,7 +1075,7 @@ def list_repos():
return repos
def get_repo(alias):
def get_repo(alias, **kwargs): # pylint: disable=unused-argument
'''
Display a repo from the /etc/opkg/*.conf
@ -1146,7 +1146,7 @@ def _mod_repo_in_file(alias, repostr, filepath):
fhandle.writelines(output)
def del_repo(alias):
def del_repo(alias, **kwargs): # pylint: disable=unused-argument
'''
Delete a repo from /etc/opkg/*.conf
@ -1260,7 +1260,7 @@ def mod_repo(alias, **kwargs):
refresh_db()
def file_list(*packages):
def file_list(*packages, **kwargs): # pylint: disable=unused-argument
'''
List the files that belong to a package. Not specifying any packages will
return a list of _every_ file on the system's package database (not
@ -1281,7 +1281,7 @@ def file_list(*packages):
return {'errors': output['errors'], 'files': files}
def file_dict(*packages):
def file_dict(*packages, **kwargs): # pylint: disable=unused-argument
'''
List the files that belong to a package, grouped by package. Not
specifying any packages will return a list of _every_ file on the system's
@ -1323,7 +1323,7 @@ def file_dict(*packages):
return {'errors': errors, 'packages': ret}
def owner(*paths):
def owner(*paths, **kwargs): # pylint: disable=unused-argument
'''
Return the name of the package that owns the file. Multiple file paths can
be passed. Like :mod:`pkg.version <salt.modules.opkg.version`, if a single

View File

@ -93,7 +93,7 @@ def _validate_partition_boundary(boundary):
'''
try:
for unit in VALID_UNITS:
if boundary.endswith(unit):
if str(boundary).endswith(unit):
return
int(boundary)
except Exception:

View File

@ -923,8 +923,9 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
salt '*' state.apply test pillar='{"foo": "bar"}'
.. note::
Values passed this way will override Pillar values set via
``pillar_roots`` or an external Pillar source.
Values passed this way will override existing Pillar values set via
``pillar_roots`` or an external Pillar source. Pillar values that
are not included in the kwarg will not be overwritten.
.. versionchanged:: 2016.3.0
GPG-encrypted CLI Pillar data is now supported via the GPG
@ -1379,6 +1380,20 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
:conf_minion:`pillarenv` minion config option nor this CLI argument is
used, all Pillar environments will be merged together.
pillar
Custom Pillar values, passed as a dictionary of key-value pairs
.. code-block:: bash
salt '*' state.sls_id my_state my_module pillar='{"foo": "bar"}'
.. note::
Values passed this way will override existing Pillar values set via
``pillar_roots`` or an external Pillar source. Pillar values that
are not included in the kwarg will not be overwritten.
.. versionadded:: Oxygen
CLI Example:
.. code-block:: bash
@ -1399,12 +1414,26 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
if opts['environment'] is None:
opts['environment'] = 'base'
pillar_override = kwargs.get('pillar')
pillar_enc = kwargs.get('pillar_enc')
if pillar_enc is None \
and pillar_override is not None \
and not isinstance(pillar_override, dict):
raise SaltInvocationError(
'Pillar data must be formatted as a dictionary, unless pillar_enc '
'is specified.'
)
try:
st_ = salt.state.HighState(opts,
pillar_override,
pillar_enc=pillar_enc,
proxy=__proxy__,
initial_pillar=_get_initial_pillar(opts))
except NameError:
st_ = salt.state.HighState(opts,
pillar_override,
pillar_enc=pillar_enc,
initial_pillar=_get_initial_pillar(opts))
if not _check_pillar(kwargs, st_.opts['pillar']):

View File

@ -55,7 +55,6 @@ def __virtual__():
'''
run Vagrant commands if possible
'''
# noinspection PyUnresolvedReferences
if salt.utils.path.which('vagrant') is None:
return False, 'The vagrant module could not be loaded: vagrant command not found'
return __virtualname__
@ -298,6 +297,11 @@ def vm_state(name='', cwd=None):
'provider': _, # the Vagrant VM provider
'name': _} # salt_id name
Known bug: if there are multiple machines in your Vagrantfile, and you request
the status of the ``primary`` machine, which you defined by leaving the ``machine``
parameter blank, then you may receive the status of all of them.
Please specify the actual machine name for each VM if there are more than one.
'''
if name:
@ -321,7 +325,7 @@ def vm_state(name='', cwd=None):
datum = {'machine': tokens[0],
'state': ' '.join(tokens[1:-1]),
'provider': tokens[-1].lstrip('(').rstrip(')'),
'name': name or get_machine_id(tokens[0], cwd)
'name': get_machine_id(tokens[0], cwd)
}
info.append(datum)
except IndexError:
@ -365,7 +369,7 @@ def init(name, # Salt_id for created VM
# passed-in keyword arguments overwrite vm dictionary values
vm_['cwd'] = cwd or vm_.get('cwd')
if not vm_['cwd']:
raise SaltInvocationError('Path to Vagrantfile must be defined by \'cwd\' argument')
raise SaltInvocationError('Path to Vagrantfile must be defined by "cwd" argument')
vm_['machine'] = machine or vm_.get('machine', machine)
vm_['runas'] = runas or vm_.get('runas', runas)
vm_['vagrant_provider'] = vagrant_provider or vm_.get('vagrant_provider', '')
@ -423,7 +427,7 @@ def shutdown(name):
'''
Send a soft shutdown (vagrant halt) signal to the named vm.
This does the same thing as vagrant.stop. Other VM control
This does the same thing as vagrant.stop. Other-VM control
modules use "stop" and "shutdown" to differentiate between
hard and soft shutdowns.
@ -476,7 +480,7 @@ def pause(name):
return ret == 0
def reboot(name):
def reboot(name, provision=False):
'''
Reboot a VM. (vagrant reload)
@ -484,12 +488,16 @@ def reboot(name):
.. code-block:: bash
salt <host> vagrant.reboot <salt_id>
salt <host> vagrant.reboot <salt_id> provision=True
:param name: The salt_id name you will use to control this VM
:param provision: (False) also re-run the Vagrant provisioning scripts.
'''
vm_ = get_vm_info(name)
machine = vm_['machine']
prov = '--provision' if provision else ''
cmd = 'vagrant reload {}'.format(machine)
cmd = 'vagrant reload {} {}'.format(machine, prov)
ret = __salt__['cmd.retcode'](cmd,
runas=vm_.get('runas'),
cwd=vm_.get('cwd'))

View File

@ -656,7 +656,7 @@ def _nic_profile(profile_name, hypervisor, **kwargs):
if key not in attributes or not attributes[key]:
attributes[key] = value
def _assign_mac(attributes):
def _assign_mac(attributes, hypervisor):
dmac = kwargs.get('dmac', None)
if dmac is not None:
log.debug('DMAC address is {0}'.format(dmac))
@ -666,11 +666,15 @@ def _nic_profile(profile_name, hypervisor, **kwargs):
msg = 'Malformed MAC address: {0}'.format(dmac)
raise CommandExecutionError(msg)
else:
attributes['mac'] = salt.utils.network.gen_mac()
if hypervisor in ['qemu', 'kvm']:
attributes['mac'] = salt.utils.network.gen_mac(
prefix='52:54:00')
else:
attributes['mac'] = salt.utils.network.gen_mac()
for interface in interfaces:
_normalize_net_types(interface)
_assign_mac(interface)
_assign_mac(interface, hypervisor)
if hypervisor in overlays:
_apply_default_overlay(interface)

View File

@ -891,11 +891,11 @@ class Pillar(object):
# Avoid circular import
import salt.utils.gitfs
import salt.pillar.git_pillar
git_pillar = salt.utils.gitfs.GitPillar(self.opts)
git_pillar.init_remotes(
git_pillar = salt.utils.gitfs.GitPillar(
self.opts,
self.ext['git'],
salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
salt.pillar.git_pillar.PER_REMOTE_ONLY)
per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY)
git_pillar.fetch_remotes()
except TypeError:
# Handle malformed ext_pillar

View File

@ -348,12 +348,6 @@ from salt.ext import six
PER_REMOTE_OVERRIDES = ('env', 'root', 'ssl_verify', 'refspecs')
PER_REMOTE_ONLY = ('name', 'mountpoint')
# Fall back to default per-remote-only. This isn't technically needed since
# salt.utils.gitfs.GitBase.init_remotes() will default to
# salt.utils.gitfs.PER_REMOTE_ONLY for this value, so this is mainly for
# runners and other modules that import salt.pillar.git_pillar.
PER_REMOTE_ONLY = salt.utils.gitfs.PER_REMOTE_ONLY
# Set up logging
log = logging.getLogger(__name__)
@ -371,7 +365,7 @@ def __virtual__():
return False
try:
salt.utils.gitfs.GitPillar(__opts__)
salt.utils.gitfs.GitPillar(__opts__, init_remotes=False)
# Initialization of the GitPillar object did not fail, so we
# know we have valid configuration syntax and that a valid
# provider was detected.
@ -387,8 +381,11 @@ def ext_pillar(minion_id, pillar, *repos): # pylint: disable=unused-argument
opts = copy.deepcopy(__opts__)
opts['pillar_roots'] = {}
opts['__git_pillar'] = True
git_pillar = salt.utils.gitfs.GitPillar(opts)
git_pillar.init_remotes(repos, PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
git_pillar = salt.utils.gitfs.GitPillar(
opts,
repos,
per_remote_overrides=PER_REMOTE_OVERRIDES,
per_remote_only=PER_REMOTE_ONLY)
if __opts__.get('__role') == 'minion':
# If masterless, fetch the remotes. We'll need to remove this once
# we make the minion daemon able to run standalone.

View File

@ -328,11 +328,14 @@ def clear_git_lock(role, remote=None, **kwargs):
salt.utils.args.invalid_kwargs(kwargs)
if role == 'gitfs':
git_objects = [salt.utils.gitfs.GitFS(__opts__)]
git_objects[0].init_remotes(
__opts__['gitfs_remotes'],
salt.fileserver.gitfs.PER_REMOTE_OVERRIDES,
salt.fileserver.gitfs.PER_REMOTE_ONLY)
git_objects = [
salt.utils.gitfs.GitFS(
__opts__,
__opts__['gitfs_remotes'],
per_remote_overrides=salt.fileserver.gitfs.PER_REMOTE_OVERRIDES,
per_remote_only=salt.fileserver.gitfs.PER_REMOTE_ONLY
)
]
elif role == 'git_pillar':
git_objects = []
for ext_pillar in __opts__['ext_pillar']:
@ -340,11 +343,11 @@ def clear_git_lock(role, remote=None, **kwargs):
if key == 'git':
if not isinstance(ext_pillar['git'], list):
continue
obj = salt.utils.gitfs.GitPillar(__opts__)
obj.init_remotes(
obj = salt.utils.gitfs.GitPillar(
__opts__,
ext_pillar['git'],
salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
salt.pillar.git_pillar.PER_REMOTE_ONLY)
per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY)
git_objects.append(obj)
elif role == 'winrepo':
winrepo_dir = __opts__['winrepo_dir']
@ -355,11 +358,12 @@ def clear_git_lock(role, remote=None, **kwargs):
(winrepo_remotes, winrepo_dir),
(__opts__['winrepo_remotes_ng'], __opts__['winrepo_dir_ng'])
):
obj = salt.utils.gitfs.WinRepo(__opts__, base_dir)
obj.init_remotes(
obj = salt.utils.gitfs.WinRepo(
__opts__,
remotes,
salt.runners.winrepo.PER_REMOTE_OVERRIDES,
salt.runners.winrepo.PER_REMOTE_ONLY)
per_remote_overrides=salt.runners.winrepo.PER_REMOTE_OVERRIDES,
per_remote_only=salt.runners.winrepo.PER_REMOTE_ONLY,
cache_root=base_dir)
git_objects.append(obj)
else:
raise SaltInvocationError('Invalid role \'{0}\''.format(role))

View File

@ -66,10 +66,11 @@ def update(branch=None, repo=None):
if pillar_type != 'git':
continue
pillar_conf = ext_pillar[pillar_type]
pillar = salt.utils.gitfs.GitPillar(__opts__)
pillar.init_remotes(pillar_conf,
salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
salt.pillar.git_pillar.PER_REMOTE_ONLY)
pillar = salt.utils.gitfs.GitPillar(
__opts__,
pillar_conf,
per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY)
for remote in pillar.remotes:
# Skip this remote if it doesn't match the search criteria
if branch is not None:

View File

@ -32,7 +32,7 @@ log = logging.getLogger(__name__)
PER_REMOTE_OVERRIDES = ('ssl_verify', 'refspecs')
# Fall back to default per-remote-only. This isn't technically needed since
# salt.utils.gitfs.GitBase.init_remotes() will default to
# salt.utils.gitfs.GitBase.__init__ will default to
# salt.utils.gitfs.PER_REMOTE_ONLY for this value, so this is mainly for
# runners and other modules that import salt.runners.winrepo.
PER_REMOTE_ONLY = salt.utils.gitfs.PER_REMOTE_ONLY
@ -216,9 +216,12 @@ def update_git_repos(opts=None, clean=False, masterless=False):
else:
# New winrepo code utilizing salt.utils.gitfs
try:
winrepo = salt.utils.gitfs.WinRepo(opts, base_dir)
winrepo.init_remotes(
remotes, PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY)
winrepo = salt.utils.gitfs.WinRepo(
opts,
remotes,
per_remote_overrides=PER_REMOTE_OVERRIDES,
per_remote_only=PER_REMOTE_ONLY,
cache_root=base_dir)
winrepo.fetch_remotes()
# Since we're not running update(), we need to manually call
# clear_old_remotes() to remove directories from remotes that

View File

@ -159,7 +159,7 @@ def formatted(name, fs_type='ext4', force=False, **kwargs):
ret['result'] = None
return ret
__salt__['disk.format_'](name, fs_type, force=force, **kwargs)
__salt__['disk.format'](name, fs_type, force=force, **kwargs)
# Repeat fstype check up to 10 times with 3s sleeping between each
# to avoid detection failing although mkfs has succeeded

369
salt/states/vagrant.py Normal file
View File

@ -0,0 +1,369 @@
# -*- coding: utf-8 -*-
r'''
.. index:: Vagrant state function
Manage Vagrant VMs
==================
Manange execution of Vagrant virtual machines on Salt minions.
Vagrant_ is a tool for building and managing virtual machine environments.
It can use various providers, such as VirtualBox_, Docker_, or VMware_, to run its VMs.
Vagrant provides some of the functionality of a light-weight hypervisor.
The combination of Salt modules, Vagrant running on the host, and a
virtual machine provider, gives hypervisor-like functionality for
developers who use Vagrant to quickly define their virtual environments.
.. _Vagrant: http://www.vagrantup.com/
.. _VirtualBox: https://www.virtualbox.org/
.. _Docker: https://www.docker.io/
.. _VMWare: https://www.vmware.com/
.. versionadded:: Oxygen
The configuration of each virtual machine is defined in a file named
``Vagrantfile`` which must exist on the VM host machine.
The essential parameters which must be defined to start a Vagrant VM
are the directory where the ``Vagrantfile`` is located \(argument ``cwd:``\),
and the username which will own the ``Vagrant box`` created for the VM \(
argument ``vagrant_runas:``\).
A single ``Vagrantfile`` may define one or more virtual machines.
Use the ``machine`` argument to chose among them. The default (blank)
value will select the ``primary`` (or only) machine in the Vagrantfile.
\[NOTE:\] Each virtual machine host must have the following:
- a working salt-minion
- a Salt sdb database configured for ``vagrant_sdb_data``.
- Vagrant installed and the ``vagrant`` command working
- a suitable VM provider
.. code-block:: yaml
# EXAMPLE:
# file /etc/salt/minion.d/vagrant_sdb.conf on the host computer
# -- this sdb database is required by the Vagrant module --
vagrant_sdb_data: # The sdb database must have this name.
driver: sqlite3 # Let's use SQLite to store the data ...
database: /var/cache/salt/vagrant.sqlite # ... in this file ...
table: sdb # ... using this table name.
create_table: True # if not present
'''
from __future__ import absolute_import
# Import Python libs
import fnmatch
# Import Salt libs
import salt.utils.args
from salt.exceptions import CommandExecutionError, SaltInvocationError
import salt.ext.six as six
__virtualname__ = 'vagrant'
def __virtual__():
'''
Only if vagrant module is available.
:return:
'''
if 'vagrant.version' in __salt__:
return __virtualname__
return False
def _vagrant_call(node, function, section, comment, status_when_done=None, **kwargs):
'''
Helper to call the vagrant functions. Wildcards supported.
:param node: The Salt-id or wildcard
:param function: the vagrant submodule to call
:param section: the name for the state call.
:param comment: what the state reply should say
:param status_when_done: the Vagrant status expected for this state
:return: the dictionary for the state reply
'''
ret = {'name': node, 'changes': {}, 'result': True, 'comment': ''}
targeted_nodes = []
if isinstance(node, six.string_types):
try: # use shortcut if a single node name
if __salt__['vagrant.get_vm_info'](node):
targeted_nodes = [node]
except SaltInvocationError:
pass
if not targeted_nodes: # the shortcut failed, do this the hard way
all_domains = __salt__['vagrant.list_domains']()
targeted_nodes = fnmatch.filter(all_domains, node)
changed_nodes = []
ignored_nodes = []
for node in targeted_nodes:
if status_when_done:
try:
present_state = __salt__['vagrant.vm_state'](node)[0]
if present_state['state'] == status_when_done:
continue # no change is needed
except (IndexError, SaltInvocationError, CommandExecutionError):
pass
try:
response = __salt__['vagrant.{0}'.format(function)](node, **kwargs)
if isinstance(response, dict):
response = response['name']
changed_nodes.append({'node': node, function: response})
except (SaltInvocationError, CommandExecutionError) as err:
ignored_nodes.append({'node': node, 'issue': str(err)})
if not changed_nodes:
ret['result'] = True
ret['comment'] = 'No changes seen'
if ignored_nodes:
ret['changes'] = {'ignored': ignored_nodes}
else:
ret['changes'] = {section: changed_nodes}
ret['comment'] = comment
return ret
def running(name, **kwargs):
r'''
Defines and starts a new VM with specified arguments, or restart a
VM (or group of VMs). (Runs ``vagrant up``.)
:param name: the Salt_id node name you wish your VM to have.
If ``name`` contains a "?" or "*" then it will re-start a group of VMs
which have been paused or stopped.
Each machine must be initially started individually using this function
or the vagrant.init execution module call.
\[NOTE:\] Keyword arguments are silently ignored when re-starting an existing VM.
Possible keyword arguments:
- cwd: The directory (path) containing the Vagrantfile
- machine: ('') the name of the machine (in the Vagrantfile) if not default
- vagrant_runas: ('root') the username who owns the vagrantbox file
- vagrant_provider: the provider to run the VM (usually 'virtualbox')
- vm: ({}) a dictionary containing these or other keyword arguments
.. code-block:: yaml
node_name:
vagrant.running
.. code-block:: yaml
node_name:
vagrant.running:
- cwd: /projects/my_project
- vagrant_runas: my_username
- machine: machine1
'''
if '*' in name or '?' in name:
return _vagrant_call(name, 'start', 'restarted',
"Machine has been restarted", "running")
else:
ret = {'name': name,
'changes': {},
'result': True,
'comment': '{0} is already running'.format(name)
}
try:
info = __salt__['vagrant.vm_state'](name)
if info[0]['state'] != 'running':
__salt__['vagrant.start'](name)
ret['changes'][name] = 'Machine started'
ret['comment'] = 'Node {0} started'.format(name)
except (SaltInvocationError, CommandExecutionError):
# there was no viable existing machine to start
ret, kwargs = _find_init_change(name, ret, **kwargs)
kwargs['start'] = True
__salt__['vagrant.init'](name, **kwargs)
ret['changes'][name] = 'Node defined and started'
ret['comment'] = 'Node {0} defined and started'.format(name)
return ret
def _find_init_change(name, ret, **kwargs):
'''
look for changes from any previous init of machine.
:return: modified ret and kwargs
'''
kwargs = salt.utils.args.clean_kwargs(**kwargs)
if 'vm' in kwargs:
kwargs.update(kwargs.pop('vm'))
# the state processing eats 'runas' so we rename
kwargs['runas'] = kwargs.pop('vagrant_runas', '')
try:
vm_ = __salt__['vagrant.get_vm_info'](name)
except SaltInvocationError:
vm_ = {}
for key, value in kwargs.items():
ret['changes'][key] = {'old': None, 'new': value}
if vm_: # test for changed values
for key in vm_:
value = vm_[key] or '' # supply a blank if value is None
if key != 'name': # will be missing in kwargs
new = kwargs.get(key, '')
if new != value:
if key == 'machine' and new == '':
continue # we don't know the default machine name
ret['changes'][key] = {'old': value, 'new': new}
return ret, kwargs
def initialized(name, **kwargs):
r'''
Defines a new VM with specified arguments, but does not start it.
:param name: the Salt_id node name you wish your VM to have.
Each machine must be initialized individually using this function
or the "vagrant.running" function, or the vagrant.init execution module call.
This command will not change the state of a running or paused machine.
Possible keyword arguments:
- cwd: The directory (path) containing the Vagrantfile
- machine: ('') the name of the machine (in the Vagrantfile) if not default
- vagrant_runas: ('root') the username who owns the vagrantbox file
- vagrant_provider: the provider to run the VM (usually 'virtualbox')
- vm: ({}) a dictionary containing these or other keyword arguments
.. code-block:: yaml
node_name1:
vagrant.initialized
- cwd: /projects/my_project
- vagrant_runas: my_username
- machine: machine1
node_name2:
vagrant.initialized
- cwd: /projects/my_project
- vagrant_runas: my_username
- machine: machine2
start_nodes:
vagrant.start:
- name: node_name?
'''
ret = {'name': name,
'changes': {},
'result': True,
'comment': 'The VM is already correctly defined'
}
# define a machine to start later
ret, kwargs = _find_init_change(name, ret, **kwargs)
if ret['changes'] == {}:
return ret
kwargs['start'] = False
__salt__['vagrant.init'](name, **kwargs)
ret['changes'][name] = 'Node initialized'
ret['comment'] = 'Node {0} defined but not started.'.format(name)
return ret
def stopped(name):
'''
Stops a VM (or VMs) by shutting it (them) down nicely. (Runs ``vagrant halt``)
:param name: May be a Salt_id node, or a POSIX-style wildcard string.
.. code-block:: yaml
node_name:
vagrant.stopped
'''
return _vagrant_call(name, 'shutdown', 'stopped',
'Machine has been shut down', 'poweroff')
def powered_off(name):
'''
Stops a VM (or VMs) by power off. (Runs ``vagrant halt``.)
This method is provided for compatibility with other VM-control
state modules. For Vagrant, the action is identical with ``stopped``.
:param name: May be a Salt_id node or a POSIX-style wildcard string.
.. code-block:: yaml
node_name:
vagrant.unpowered
'''
return _vagrant_call(name, 'stop', 'unpowered',
'Machine has been powered off', 'poweroff')
def destroyed(name):
'''
Stops a VM (or VMs) and removes all refences to it (them). (Runs ``vagrant destroy``.)
Subsequent re-use of the same machine will requere another operation of ``vagrant.running``
or a call to the ``vagrant.init`` execution module.
:param name: May be a Salt_id node or a POSIX-style wildcard string.
.. code-block:: yaml
node_name:
vagrant.destroyed
'''
return _vagrant_call(name, 'destroy', 'destroyed',
'Machine has been removed')
def paused(name):
'''
Stores the state of a VM (or VMs) for fast restart. (Runs ``vagrant suspend``.)
:param name: May be a Salt_id node or a POSIX-style wildcard string.
.. code-block:: yaml
node_name:
vagrant.paused
'''
return _vagrant_call(name, 'pause', 'paused',
'Machine has been suspended', 'saved')
def rebooted(name):
'''
Reboots a running, paused, or stopped VM (or VMs). (Runs ``vagrant reload``.)
The will re-run the provisioning
:param name: May be a Salt_id node or a POSIX-style wildcard string.
.. code-block:: yaml
node_name:
vagrant.reloaded
'''
return _vagrant_call(name, 'reboot', 'rebooted', 'Machine has been reloaded')

View File

@ -67,6 +67,10 @@ def managed(name,
name
Path to the virtualenv.
venv_bin: virtualenv
The name (and optionally path) of the virtualenv command. This can also
be set globally in the minion config file as ``virtualenv.venv_bin``.
requirements: None
Path to a pip requirements file. If the path begins with ``salt://``
the file will be transferred from the master file server.

View File

@ -398,13 +398,14 @@ def bootstrap(vm_, opts=None):
# NOTE: deploy_kwargs is also used to pass inline_script variable content
# to run_inline_script function
host = salt.config.get_cloud_config_value('ssh_host', vm_, opts)
deploy_kwargs = {
'opts': opts,
'host': vm_['ssh_host'],
'host': host,
'port': salt.config.get_cloud_config_value(
'ssh_port', vm_, opts, default=22
),
'salt_host': vm_.get('salt_host', vm_['ssh_host']),
'salt_host': vm_.get('salt_host', host),
'username': ssh_username,
'script': deploy_script_code,
'inline_script': inline_script_config,

View File

@ -20,6 +20,8 @@ import shutil
import stat
import subprocess
import time
import tornado.ioloop
import weakref
from datetime import datetime
# Import salt libs
@ -1925,12 +1927,47 @@ class GitBase(object):
'''
Base class for gitfs/git_pillar
'''
def __init__(self, opts, git_providers=None, cache_root=None):
def __init__(self, opts, remotes=None, per_remote_overrides=(),
per_remote_only=PER_REMOTE_ONLY, git_providers=None,
cache_root=None, init_remotes=True):
'''
IMPORTANT: If specifying a cache_root, understand that this is also
where the remotes will be cloned. A non-default cache_root is only
really designed right now for winrepo, as its repos need to be checked
out into the winrepo locations and not within the cachedir.
As of the Oxygen release cycle, the classes used to interface with
Pygit2 and GitPython can be overridden by passing the git_providers
argument when spawning a class instance. This allows for one to write
classes which inherit from salt.utils.gitfs.Pygit2 or
salt.utils.gitfs.GitPython, and then direct one of the GitBase
subclasses (GitFS, GitPillar, WinRepo) to use the custom class. For
example:
.. code-block:: Python
import salt.utils.gitfs
from salt.fileserver.gitfs import PER_REMOTE_OVERRIDES, PER_REMOTE_ONLY
class CustomPygit2(salt.utils.gitfs.Pygit2):
def fetch_remotes(self):
...
Alternate fetch behavior here
...
git_providers = {
'pygit2': CustomPygit2,
'gitpython': salt.utils.gitfs.GitPython,
}
gitfs = salt.utils.gitfs.GitFS(
__opts__,
__opts__['gitfs_remotes'],
per_remote_overrides=PER_REMOTE_OVERRIDES,
per_remote_only=PER_REMOTE_ONLY,
git_providers=git_providers)
gitfs.fetch_remotes()
'''
self.opts = opts
self.git_providers = git_providers if git_providers is not None \
@ -1946,8 +1983,13 @@ class GitBase(object):
self.hash_cachedir = salt.utils.path.join(self.cache_root, 'hash')
self.file_list_cachedir = salt.utils.path.join(
self.opts['cachedir'], 'file_lists', self.role)
if init_remotes:
self.init_remotes(
remotes if remotes is not None else [],
per_remote_overrides,
per_remote_only)
def init_remotes(self, remotes, per_remote_overrides,
def init_remotes(self, remotes, per_remote_overrides=(),
per_remote_only=PER_REMOTE_ONLY):
'''
Initialize remotes
@ -2471,9 +2513,51 @@ class GitFS(GitBase):
'''
Functionality specific to the git fileserver backend
'''
def __init__(self, opts):
self.role = 'gitfs'
super(GitFS, self).__init__(opts)
role = 'gitfs'
instance_map = weakref.WeakKeyDictionary()
def __new__(cls, opts, remotes=None, per_remote_overrides=(),
per_remote_only=PER_REMOTE_ONLY, git_providers=None,
cache_root=None, init_remotes=True):
'''
If we are not initializing remotes (such as in cases where we just want
to load the config so that we can run clear_cache), then just return a
new __init__'ed object. Otherwise, check the instance map and re-use an
instance if one exists for the current process. Weak references are
used to ensure that we garbage collect instances for threads which have
exited.
'''
# No need to get the ioloop reference if we're not initializing remotes
io_loop = tornado.ioloop.IOLoop.current() if init_remotes else None
if not init_remotes or io_loop not in cls.instance_map:
# We only evaluate the second condition in this if statement if
# we're initializing remotes, so we won't get here unless io_loop
# is something other than None.
obj = object.__new__(cls)
super(GitFS, obj).__init__(
opts,
remotes if remotes is not None else [],
per_remote_overrides=per_remote_overrides,
per_remote_only=per_remote_only,
git_providers=git_providers if git_providers is not None
else GIT_PROVIDERS,
cache_root=cache_root,
init_remotes=init_remotes)
if not init_remotes:
log.debug('Created gitfs object with uninitialized remotes')
else:
log.debug('Created gitfs object for process %s', os.getpid())
# Add to the instance map so we can re-use later
cls.instance_map[io_loop] = obj
return obj
log.debug('Re-using gitfs object for process %s', os.getpid())
return cls.instance_map[io_loop]
def __init__(self, opts, remotes, per_remote_overrides=(), # pylint: disable=super-init-not-called
per_remote_only=PER_REMOTE_ONLY, git_providers=None,
cache_root=None, init_remotes=True):
# Initialization happens above in __new__(), so don't do anything here
pass
def dir_list(self, load):
'''
@ -2755,9 +2839,7 @@ class GitPillar(GitBase):
'''
Functionality specific to the git external pillar
'''
def __init__(self, opts):
self.role = 'git_pillar'
super(GitPillar, self).__init__(opts)
role = 'git_pillar'
def checkout(self):
'''
@ -2845,9 +2927,7 @@ class WinRepo(GitBase):
'''
Functionality specific to the winrepo runner
'''
def __init__(self, opts, winrepo_dir):
self.role = 'winrepo'
super(WinRepo, self).__init__(opts, cache_root=winrepo_dir)
role = 'winrepo'
def checkout(self):
'''

View File

@ -206,8 +206,13 @@ def wrap_tmpl_func(render_str):
if six.PY2:
output = output.encode(SLS_ENCODING)
if salt.utils.platform.is_windows():
newline = False
if output.endswith(('\n', os.linesep)):
newline = True
# Write out with Windows newlines
output = os.linesep.join(output.splitlines())
if newline:
output += os.linesep
except SaltRenderError as exc:
log.error("Rendering exception occurred: {0}".format(exc))
@ -331,7 +336,7 @@ def render_jinja_tmpl(tmplstr, context, tmplpath=None):
# http://jinja.pocoo.org/docs/api/#unicode
tmplstr = tmplstr.decode(SLS_ENCODING)
if tmplstr.endswith('\n'):
if tmplstr.endswith(os.linesep):
newline = True
if not saltenv:
@ -441,7 +446,7 @@ def render_jinja_tmpl(tmplstr, context, tmplpath=None):
# Workaround a bug in Jinja that removes the final newline
# (https://github.com/mitsuhiko/jinja2/issues/75)
if newline:
output += '\n'
output += os.linesep
return output

View File

@ -281,7 +281,10 @@ def vb_get_network_addresses(machine_name=None, machine=None):
# We can't trust virtualbox to give us up to date guest properties if the machine isn't running
# For some reason it may give us outdated (cached?) values
if machine.state == _virtualboxManager.constants.MachineState_Running:
total_slots = int(machine.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/Count'))
try:
total_slots = int(machine.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/Count'))
except ValueError:
total_slots = 0
for i in range(total_slots):
try:
address = machine.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/{0}/V4/IP'.format(i))

View File

@ -2,18 +2,18 @@
# Import python libs
from __future__ import absolute_import
import string
import grp
import os
import random
import string
# Import Salt Testing libs
from tests.support.case import ModuleCase
from tests.support.helpers import destructiveTest, skip_if_not_root
# Import 3rd-party libs
# Import Salt libs
from salt.ext.six.moves import range
import os
import grp
from salt import utils
import salt.utils.files
@skip_if_not_root
@ -66,7 +66,7 @@ class GroupModuleTest(ModuleCase):
'''
defs_file = '/etc/login.defs'
if os.path.exists(defs_file):
with utils.fopen(defs_file) as defs_fd:
with salt.utils.files.fopen(defs_file) as defs_fd:
login_defs = dict([x.split()
for x in defs_fd.readlines()
if x.strip()
@ -102,12 +102,12 @@ class GroupModuleTest(ModuleCase):
'''
Test the add group function
'''
#add a new group
# add a new group
self.assertTrue(self.run_function('group.add', [self._group, self._gid]))
group_info = self.run_function('group.info', [self._group])
self.assertEqual(group_info['name'], self._group)
self.assertEqual(group_info['gid'], self._gid)
#try adding the group again
# try adding the group again
self.assertFalse(self.run_function('group.add', [self._group, self._gid]))
@destructiveTest
@ -124,7 +124,7 @@ class GroupModuleTest(ModuleCase):
group_info = self.run_function('group.info', [self._group])
self.assertEqual(group_info['name'], self._group)
self.assertTrue(gid_min <= group_info['gid'] <= gid_max)
#try adding the group again
# try adding the group again
self.assertFalse(self.run_function('group.add',
[self._group]))
@ -142,7 +142,7 @@ class GroupModuleTest(ModuleCase):
group_info = self.run_function('group.info', [self._group])
self.assertEqual(group_info['name'], self._group)
self.assertEqual(group_info['gid'], gid)
#try adding the group again
# try adding the group again
self.assertFalse(self.run_function('group.add',
[self._group, gid]))
@ -153,10 +153,10 @@ class GroupModuleTest(ModuleCase):
'''
self.assertTrue(self.run_function('group.add', [self._group]))
#correct functionality
# correct functionality
self.assertTrue(self.run_function('group.delete', [self._group]))
#group does not exist
# group does not exist
self.assertFalse(self.run_function('group.delete', [self._no_group]))
@destructiveTest
@ -193,11 +193,11 @@ class GroupModuleTest(ModuleCase):
self.assertTrue(self.run_function('group.adduser', [self._group, self._user]))
group_info = self.run_function('group.info', [self._group])
self.assertIn(self._user, group_info['members'])
#try add a non existing user
# try to add a non existing user
self.assertFalse(self.run_function('group.adduser', [self._group, self._no_user]))
#try add a user to non existing group
# try to add a user to non existing group
self.assertFalse(self.run_function('group.adduser', [self._no_group, self._user]))
#try add a non existing user to a non existing group
# try to add a non existing user to a non existing group
self.assertFalse(self.run_function('group.adduser', [self._no_group, self._no_user]))
@destructiveTest

View File

@ -5,10 +5,12 @@
# Import Python libs
from __future__ import absolute_import
import errno
import os
import shutil
import tempfile
import textwrap
import tornado.ioloop
import logging
import stat
try:
@ -40,18 +42,26 @@ import salt.utils.win_functions
log = logging.getLogger(__name__)
TMP_SOCK_DIR = tempfile.mkdtemp(dir=TMP)
TMP_REPO_DIR = os.path.join(TMP, 'gitfs_root')
INTEGRATION_BASE_FILES = os.path.join(FILES, 'file', 'base')
def _rmtree_error(func, path, excinfo):
os.chmod(path, stat.S_IWRITE)
func(path)
@skipIf(not HAS_GITPYTHON, 'GitPython is not installed')
class GitfsConfigTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
self.tmp_cachedir = tempfile.mkdtemp(dir=TMP)
self.tmp_sock_dir = tempfile.mkdtemp(dir=TMP)
return {
gitfs: {
'__opts__': {
'cachedir': self.tmp_cachedir,
'sock_dir': self.tmp_sock_dir,
'sock_dir': TMP_SOCK_DIR,
'gitfs_root': 'salt',
'fileserver_backend': ['git'],
'gitfs_base': 'master',
@ -81,9 +91,17 @@ class GitfsConfigTestCase(TestCase, LoaderModuleMockMixin):
}
}
@classmethod
def setUpClass(cls):
# Clear the instance map so that we make sure to create a new instance
# for this test class.
try:
del salt.utils.gitfs.GitFS.instance_map[tornado.ioloop.IOLoop.current()]
except KeyError:
pass
def tearDown(self):
shutil.rmtree(self.tmp_cachedir)
shutil.rmtree(self.tmp_sock_dir)
def test_per_saltenv_config(self):
opts_override = textwrap.dedent('''
@ -109,10 +127,11 @@ class GitfsConfigTestCase(TestCase, LoaderModuleMockMixin):
- mountpoint: abc
''')
with patch.dict(gitfs.__opts__, yaml.safe_load(opts_override)):
git_fs = salt.utils.gitfs.GitFS(gitfs.__opts__)
git_fs.init_remotes(
git_fs = salt.utils.gitfs.GitFS(
gitfs.__opts__,
gitfs.__opts__['gitfs_remotes'],
gitfs.PER_REMOTE_OVERRIDES, gitfs.PER_REMOTE_ONLY)
per_remote_overrides=gitfs.PER_REMOTE_OVERRIDES,
per_remote_only=gitfs.PER_REMOTE_ONLY)
# repo1 (branch: foo)
# The mountpoint should take the default (from gitfs_mountpoint), while
@ -169,14 +188,12 @@ class GitFSTest(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
self.tmp_cachedir = tempfile.mkdtemp(dir=TMP)
self.tmp_sock_dir = tempfile.mkdtemp(dir=TMP)
self.tmp_repo_dir = os.path.join(TMP, 'gitfs_root')
return {
gitfs: {
'__opts__': {
'cachedir': self.tmp_cachedir,
'sock_dir': self.tmp_sock_dir,
'gitfs_remotes': ['file://' + self.tmp_repo_dir],
'sock_dir': TMP_SOCK_DIR,
'gitfs_remotes': ['file://' + TMP_REPO_DIR],
'gitfs_root': '',
'fileserver_backend': ['git'],
'gitfs_base': 'master',
@ -206,26 +223,26 @@ class GitFSTest(TestCase, LoaderModuleMockMixin):
}
}
def setUp(self):
'''
We don't want to check in another .git dir into GH because that just gets messy.
Instead, we'll create a temporary repo on the fly for the tests to examine.
'''
if not gitfs.__virtual__():
self.skipTest("GitFS could not be loaded. Skipping GitFS tests!")
self.integration_base_files = os.path.join(FILES, 'file', 'base')
@classmethod
def setUpClass(cls):
# Clear the instance map so that we make sure to create a new instance
# for this test class.
try:
del salt.utils.gitfs.GitFS.instance_map[tornado.ioloop.IOLoop.current()]
except KeyError:
pass
# Create the dir if it doesn't already exist
try:
shutil.copytree(self.integration_base_files, self.tmp_repo_dir + '/')
shutil.copytree(INTEGRATION_BASE_FILES, TMP_REPO_DIR + '/')
except OSError:
# We probably caught an error because files already exist. Ignore
pass
try:
repo = git.Repo(self.tmp_repo_dir)
repo = git.Repo(TMP_REPO_DIR)
except git.exc.InvalidGitRepositoryError:
repo = git.Repo.init(self.tmp_repo_dir)
repo = git.Repo.init(TMP_REPO_DIR)
if 'USERNAME' not in os.environ:
try:
@ -238,9 +255,19 @@ class GitFSTest(TestCase, LoaderModuleMockMixin):
'\'root\'.')
os.environ['USERNAME'] = 'root'
repo.index.add([x for x in os.listdir(self.tmp_repo_dir)
repo.index.add([x for x in os.listdir(TMP_REPO_DIR)
if x != '.git'])
repo.index.commit('Test')
def setUp(self):
'''
We don't want to check in another .git dir into GH because that just
gets messy. Instead, we'll create a temporary repo on the fly for the
tests to examine.
'''
if not gitfs.__virtual__():
self.skipTest("GitFS could not be loaded. Skipping GitFS tests!")
self.tmp_cachedir = tempfile.mkdtemp(dir=TMP)
gitfs.update()
def tearDown(self):
@ -248,17 +275,11 @@ class GitFSTest(TestCase, LoaderModuleMockMixin):
Remove the temporary git repository and gitfs cache directory to ensure
a clean environment for each test.
'''
shutil.rmtree(self.tmp_repo_dir, onerror=self._rmtree_error)
shutil.rmtree(self.tmp_cachedir, onerror=self._rmtree_error)
shutil.rmtree(self.tmp_sock_dir, onerror=self._rmtree_error)
del self.tmp_repo_dir
del self.tmp_cachedir
del self.tmp_sock_dir
del self.integration_base_files
def _rmtree_error(self, func, path, excinfo):
os.chmod(path, stat.S_IWRITE)
func(path)
try:
shutil.rmtree(self.tmp_cachedir, onerror=_rmtree_error)
except OSError as exc:
if exc.errno != errno.EEXIST:
raise
def test_file_list(self):
ret = gitfs.file_list(LOAD)

View File

@ -428,6 +428,8 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
controllers = root.findall('.//devices/controller')
# There should be no controller
self.assertTrue(len(controllers) == 0)
# kvm mac address shoud start with 52:54:00
self.assertTrue("mac address='52:54:00" in xml_data)
def test_mixed_dict_and_list_as_profile_objects(self):

View File

@ -100,7 +100,7 @@ class BlockdevTestCase(TestCase, LoaderModuleMockMixin):
# Test state return when block device format fails
with patch.dict(blockdev.__salt__, {'cmd.run': MagicMock(return_value=mock_ext4),
'disk.format_': MagicMock(return_value=True)}):
'disk.format': MagicMock(return_value=True)}):
comt = ('Failed to format {0}'.format(name))
ret.update({'comment': comt, 'result': False})
with patch.object(salt.utils.path, 'which',

View File

@ -33,6 +33,7 @@ from salt.utils.jinja import (
)
from salt.utils.templates import JINJA, render_jinja_tmpl
from salt.utils.odict import OrderedDict
import salt.utils.stringutils
# Import 3rd party libs
import yaml
@ -176,12 +177,9 @@ class TestGetTemplate(TestCase):
with salt.utils.files.fopen(fn_) as fp_:
out = render_jinja_tmpl(
fp_.read(),
dict(
opts=self.local_opts,
saltenv='test',
salt=self.local_salt
))
self.assertEqual(out, 'world\n')
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt)
)
self.assertEqual(out, 'world' + os.linesep)
def test_fallback_noloader(self):
'''
@ -192,12 +190,9 @@ class TestGetTemplate(TestCase):
with salt.utils.files.fopen(filename) as fp_:
out = render_jinja_tmpl(
fp_.read(),
dict(
opts=self.local_opts,
saltenv='test',
salt=self.local_salt
))
self.assertEqual(out, 'Hey world !a b !\n')
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt)
)
self.assertEqual(out, 'Hey world !a b !' + os.linesep)
def test_saltenv(self):
'''
@ -216,7 +211,7 @@ class TestGetTemplate(TestCase):
'file_roots': self.local_opts['file_roots'],
'pillar_roots': self.local_opts['pillar_roots']},
a='Hi', b='Salt', saltenv='test', salt=self.local_salt))
self.assertEqual(out, 'Hey world !Hi Salt !\n')
self.assertEqual(out, 'Hey world !Hi Salt !' + os.linesep)
self.assertEqual(fc.requests[0]['path'], 'salt://macro')
def test_macro_additional_log_for_generalexc(self):
@ -225,7 +220,7 @@ class TestGetTemplate(TestCase):
more output from trace.
'''
expected = r'''Jinja error:.*division.*
.*/macrogeneral\(2\):
.*macrogeneral\(2\):
---
\{% macro mymacro\(\) -%\}
\{\{ 1/0 \}\} <======================
@ -249,7 +244,7 @@ class TestGetTemplate(TestCase):
more output from trace.
'''
expected = r'''Jinja variable 'b' is undefined
.*/macroundefined\(2\):
.*macroundefined\(2\):
---
\{% macro mymacro\(\) -%\}
\{\{b.greetee\}\} <-- error is here <======================
@ -272,7 +267,7 @@ class TestGetTemplate(TestCase):
If we failed in a macro, get more output from trace.
'''
expected = r'''Jinja syntax error: expected token .*end.*got '-'.*
.*/macroerror\(2\):
.*macroerror\(2\):
---
# macro
\{% macro mymacro\(greeting, greetee='world'\) -\} <-- error is here <======================
@ -302,7 +297,7 @@ class TestGetTemplate(TestCase):
'file_roots': self.local_opts['file_roots'],
'pillar_roots': self.local_opts['pillar_roots']},
a='Hi', b='Sàlt', saltenv='test', salt=self.local_salt))
self.assertEqual(out, u'Hey world !Hi Sàlt !\n')
self.assertEqual(out, salt.utils.stringutils.to_unicode('Hey world !Hi Sàlt !' + os.linesep))
self.assertEqual(fc.requests[0]['path'], 'salt://macro')
filename = os.path.join(TEMPLATES_DIR, 'files', 'test', 'non_ascii')
@ -313,7 +308,7 @@ class TestGetTemplate(TestCase):
'file_roots': self.local_opts['file_roots'],
'pillar_roots': self.local_opts['pillar_roots']},
a='Hi', b='Sàlt', saltenv='test', salt=self.local_salt))
self.assertEqual(u'Assunção\n', out)
self.assertEqual(u'Assunção' + os.linesep, out)
self.assertEqual(fc.requests[0]['path'], 'salt://macro')
@skipIf(HAS_TIMELIB is False, 'The `timelib` library is not installed.')
@ -376,8 +371,8 @@ class TestGetTemplate(TestCase):
with salt.utils.files.fopen(out['data']) as fp:
result = fp.read()
if six.PY2:
result = result.decode('utf-8')
self.assertEqual(u'Assunção\n', result)
result = salt.utils.stringutils.to_unicode(result)
self.assertEqual(salt.utils.stringutils.to_unicode('Assunção' + os.linesep), result)
def test_get_context_has_enough_context(self):
template = '1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf'

View File

@ -439,7 +439,7 @@ class PillarTestCase(TestCase):
def _setup_test_topfile_mocks(self, Matcher, get_file_client,
nodegroup_order, glob_order):
# Write a simple topfile and two pillar state files
self.top_file = tempfile.NamedTemporaryFile(dir=TMP)
self.top_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
s = '''
base:
group:
@ -456,19 +456,19 @@ base:
'''.format(nodegroup_order=nodegroup_order, glob_order=glob_order)
self.top_file.write(salt.utils.stringutils.to_bytes(s))
self.top_file.flush()
self.ssh_file = tempfile.NamedTemporaryFile(dir=TMP)
self.ssh_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
self.ssh_file.write(b'''
ssh:
foo
''')
self.ssh_file.flush()
self.ssh_minion_file = tempfile.NamedTemporaryFile(dir=TMP)
self.ssh_minion_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
self.ssh_minion_file.write(b'''
ssh:
bar
''')
self.ssh_minion_file.flush()
self.generic_file = tempfile.NamedTemporaryFile(dir=TMP)
self.generic_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
self.generic_file.write(b'''
generic:
key1:
@ -478,7 +478,7 @@ generic:
sub_key1: []
''')
self.generic_file.flush()
self.generic_minion_file = tempfile.NamedTemporaryFile(dir=TMP)
self.generic_minion_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
self.generic_minion_file.write(b'''
generic:
key1:
@ -507,7 +507,7 @@ generic:
client.get_state.side_effect = get_state
def _setup_test_include_mocks(self, Matcher, get_file_client):
self.top_file = top_file = tempfile.NamedTemporaryFile(dir=TMP)
self.top_file = top_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
top_file.write(b'''
base:
'*':
@ -518,21 +518,21 @@ base:
- test
''')
top_file.flush()
self.init_sls = init_sls = tempfile.NamedTemporaryFile(dir=TMP)
self.init_sls = init_sls = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
init_sls.write(b'''
include:
- test.sub1
- test.sub2
''')
init_sls.flush()
self.sub1_sls = sub1_sls = tempfile.NamedTemporaryFile(dir=TMP)
self.sub1_sls = sub1_sls = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
sub1_sls.write(b'''
p1:
- value1_1
- value1_2
''')
sub1_sls.flush()
self.sub2_sls = sub2_sls = tempfile.NamedTemporaryFile(dir=TMP)
self.sub2_sls = sub2_sls = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
sub2_sls.write(b'''
p1:
- value1_3

View File

@ -37,18 +37,19 @@ class TestGitFSProvider(TestCase):
MagicMock(return_value=True)):
with patch.object(role_class, 'verify_pygit2',
MagicMock(return_value=False)):
args = [OPTS]
args = [OPTS, {}]
kwargs = {'init_remotes': False}
if role_name == 'winrepo':
args.append('/tmp/winrepo-dir')
kwargs['cache_root'] = '/tmp/winrepo-dir'
with patch.dict(OPTS, {key: provider}):
# Try to create an instance with uppercase letters in
# provider name. If it fails then a
# FileserverConfigError will be raised, so no assert is
# necessary.
role_class(*args)
# Now try to instantiate an instance with all lowercase
# letters. Again, no need for an assert here.
role_class(*args)
role_class(*args, **kwargs)
# Now try to instantiate an instance with all lowercase
# letters. Again, no need for an assert here.
role_class(*args, **kwargs)
def test_valid_provider(self):
'''
@ -73,12 +74,13 @@ class TestGitFSProvider(TestCase):
verify = 'verify_pygit2'
mock2 = _get_mock(verify, provider)
with patch.object(role_class, verify, mock2):
args = [OPTS]
args = [OPTS, {}]
kwargs = {'init_remotes': False}
if role_name == 'winrepo':
args.append('/tmp/winrepo-dir')
kwargs['cache_root'] = '/tmp/winrepo-dir'
with patch.dict(OPTS, {key: provider}):
role_class(*args)
role_class(*args, **kwargs)
with patch.dict(OPTS, {key: 'foo'}):
# Set the provider name to a known invalid provider
@ -86,5 +88,5 @@ class TestGitFSProvider(TestCase):
self.assertRaises(
FileserverConfigError,
role_class,
*args
)
*args,
**kwargs)