mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch 'badsid' of https://github.com/morganwillcock/salt into badsid
This commit is contained in:
commit
f3af106e33
31 changed files with 852 additions and 201 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -91,3 +91,8 @@ tests/integration/cloud/providers/pki/minions
|
|||
|
||||
# Ignore tox virtualenvs
|
||||
/.tox/
|
||||
|
||||
# Ignore kitchen stuff
|
||||
.kitchen
|
||||
.bundle
|
||||
Gemfile.lock
|
||||
|
|
187
.kitchen.yml
Normal file
187
.kitchen.yml
Normal file
|
@ -0,0 +1,187 @@
|
|||
---
|
||||
<% vagrant = system('which vagrant 2>/dev/null >/dev/null') %>
|
||||
<% version = '2017.7.2' %>
|
||||
<% platformsfile = ENV['SALT_KITCHEN_PLATFORMS'] || '.kitchen/platforms.yml' %>
|
||||
<% driverfile = ENV['SALT_KITCHEN_DRIVER'] || '.kitchen/driver.yml' %>
|
||||
|
||||
<% if File.exists?(driverfile) %>
|
||||
<%= ERB.new(File.read(driverfile)).result %>
|
||||
<% else %>
|
||||
driver:
|
||||
name: docker
|
||||
use_sudo: false
|
||||
privileged: true
|
||||
username: root
|
||||
volume:
|
||||
- /var/run/docker.sock:/docker.sock
|
||||
cap_add:
|
||||
- sys_admin
|
||||
disable_upstart: false
|
||||
provision_command:
|
||||
- echo 'L /run/docker.sock - - - - /docker.sock' > /etc/tmpfiles.d/docker.conf
|
||||
<% end %>
|
||||
|
||||
sudo: false
|
||||
provisioner:
|
||||
name: salt_solo
|
||||
salt_install: bootstrap
|
||||
salt_version: latest
|
||||
salt_bootstrap_url: https://bootstrap.saltstack.com
|
||||
salt_bootstrap_options: -X stable <%= version %>
|
||||
log_level: info
|
||||
require_chef: false
|
||||
remote_states:
|
||||
name: git://github.com/saltstack/salt-jenkins.git
|
||||
branch: 2017.7
|
||||
repo: git
|
||||
testingdir: /testing
|
||||
salt_copy_filter:
|
||||
- .bundle
|
||||
- .git
|
||||
- .gitignore
|
||||
- .kitchen
|
||||
- .kitchen.yml
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- README.rst
|
||||
- .travis.yml
|
||||
state_top:
|
||||
base:
|
||||
"*":
|
||||
- git.salt
|
||||
- kitchen
|
||||
<% if File.exists?(platformsfile) %>
|
||||
<%= ERB.new(File.read(platformsfile)).result %>
|
||||
<% else %>
|
||||
platforms:
|
||||
- name: fedora
|
||||
driver_config:
|
||||
image: fedora:latest
|
||||
run_command: /usr/lib/systemd/systemd
|
||||
provisioner:
|
||||
salt_bootstrap_options: -X git v<%= version %> >/dev/null
|
||||
- name: centos-7
|
||||
driver_config:
|
||||
run_command: /usr/lib/systemd/systemd
|
||||
- name: centos-6
|
||||
driver_config:
|
||||
run_command: /sbin/init
|
||||
provision_command:
|
||||
- yum install -y upstart
|
||||
provisioner:
|
||||
salt_bootstrap_options: -P -y -x python2.7 -X git v<%= version %> >/dev/null
|
||||
- name: ubuntu-rolling
|
||||
driver_config:
|
||||
image: ubuntu:rolling
|
||||
run_command: /lib/systemd/systemd
|
||||
provisioner:
|
||||
salt_bootstrap_url: https://raw.githubusercontent.com/saltstack/salt-bootstrap/develop/bootstrap-salt.sh
|
||||
- name: ubuntu-16.04
|
||||
driver_config:
|
||||
run_command: /lib/systemd/systemd
|
||||
- name: ubuntu-14.04
|
||||
driver_config:
|
||||
run_command: /sbin/init
|
||||
provision_command:
|
||||
- rm -f /sbin/initctl
|
||||
- dpkg-divert --local --rename --remove /sbin/initctl
|
||||
- name: debian-8
|
||||
driver_config:
|
||||
run_command: /lib/systemd/systemd
|
||||
provision_command:
|
||||
- apt-get install -y dbus
|
||||
- echo 'L /run/docker.sock - - - - /docker.sock' > /etc/tmpfiles.d/docker.conf
|
||||
- name: debian-9
|
||||
driver_config:
|
||||
run_command: /lib/systemd/systemd
|
||||
- name: arch
|
||||
driver_config:
|
||||
image: base/archlinux
|
||||
run_command: /usr/lib/systemd/systemd
|
||||
provision_command:
|
||||
- pacman -Syu --noconfirm systemd
|
||||
- systemctl enable sshd
|
||||
- echo 'L /run/docker.sock - - - - /docker.sock' > /etc/tmpfiles.d/docker.conf
|
||||
provisioner:
|
||||
salt_bootstrap_options: -X git v<%= version %> >/dev/null
|
||||
- name: opensuse
|
||||
driver_config:
|
||||
run_command: /usr/lib/systemd/systemd
|
||||
provision_command:
|
||||
- systemctl enable sshd.service
|
||||
- echo 'L /run/docker.sock - - - - /docker.sock' > /etc/tmpfiles.d/docker.conf
|
||||
provisioner:
|
||||
salt_bootstrap_options: -X git v<%= version %> >/dev/null
|
||||
<% if vagrant != false %>
|
||||
- name: windows-2012r2
|
||||
driver:
|
||||
box: mwrock/Windows2012R2
|
||||
communicator: winrm
|
||||
name: vagrant
|
||||
gui: true
|
||||
username: administrator
|
||||
password: Pass@word1
|
||||
provisioner:
|
||||
init_environment: |
|
||||
Clear-Host
|
||||
$AddedLocation ="c:\salt"
|
||||
$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
|
||||
$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path
|
||||
$NewPath= $OldPath + ’;’ + $AddedLocation
|
||||
Set-ItemProperty -Path "$Reg" -Name PATH –Value $NewPath
|
||||
salt_bootstrap_url: https://raw.githubusercontent.com/saltstack/salt-bootstrap/develop/bootstrap-salt.ps1
|
||||
salt_bootstrap_options: ''
|
||||
- name: windows-2016
|
||||
driver:
|
||||
box: mwrock/Windows2016
|
||||
communicator: winrm
|
||||
name: vagrant
|
||||
username: Vagrant
|
||||
password: vagrant
|
||||
gui: true
|
||||
provisioner:
|
||||
init_environment: |
|
||||
Clear-Host
|
||||
$AddedLocation ="c:\salt;c:\salt\bin\Scripts"
|
||||
$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
|
||||
$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path
|
||||
$NewPath= $OldPath + ’;’ + $AddedLocation
|
||||
Set-ItemProperty -Path "$Reg" -Name PATH –Value $NewPath
|
||||
salt_bootstrap_url: https://raw.githubusercontent.com/saltstack/salt-bootstrap/develop/bootstrap-salt.ps1
|
||||
salt_bootstrap_options: ''
|
||||
<% end %>
|
||||
<% end %>
|
||||
suites:
|
||||
- name: py2
|
||||
provisioner:
|
||||
pillars:
|
||||
top.sls:
|
||||
base:
|
||||
"*":
|
||||
- jenkins
|
||||
jenkins.sls:
|
||||
testing_dir: /tmp/kitchen/testing
|
||||
clone_repo: false
|
||||
salttesting_namespec: salttesting==2017.6.1
|
||||
- name: py3
|
||||
provisioner:
|
||||
pillars:
|
||||
top.sls:
|
||||
base:
|
||||
"*":
|
||||
- jenkins
|
||||
jenkins.sls:
|
||||
testing_dir: /tmp/kitchen/testing
|
||||
clone_repo: false
|
||||
py3: true
|
||||
salttesting_namespec: salttesting==2017.6.1
|
||||
verifier:
|
||||
name: shell
|
||||
remote_exec: true
|
||||
sudo: false
|
||||
live_stream: {}
|
||||
<% if ENV['TESTOPTS'].nil? %>
|
||||
command: '$(kitchen) /tmp/kitchen/testing/tests/runtests.py --run-destructive --sysinfo --transport=zeromq --output-columns=80 --ssh --coverage-xml=/tmp/coverage.xml --xml=/tmp/xml-unittests-output'
|
||||
<% else %>
|
||||
command: '$(kitchen) /tmp/kitchen/testing/tests/runtests.py --run-destructive --output-columns 80 <%= ENV["TESTOPTS"] %>'
|
||||
<% end %>
|
23
Gemfile
Normal file
23
Gemfile
Normal file
|
@ -0,0 +1,23 @@
|
|||
# This file is only used for running the test suite with kitchen-salt.
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "test-kitchen"
|
||||
gem "kitchen-salt", :git => 'https://github.com/saltstack/kitchen-salt.git'
|
||||
gem 'git'
|
||||
|
||||
group :docker do
|
||||
gem 'kitchen-docker', :git => 'https://github.com/test-kitchen/kitchen-docker.git'
|
||||
end
|
||||
|
||||
group :opennebula do
|
||||
gem 'kitchen-opennebula', :git => 'https://github.com/gtmanfred/kitchen-opennebula.git'
|
||||
gem 'xmlrpc'
|
||||
end
|
||||
|
||||
group :windows do
|
||||
gem 'vagrant-wrapper'
|
||||
gem 'kitchen-vagrant'
|
||||
gem 'winrm', '~>2.0'
|
||||
gem 'winrm-fs', '~>1.0'
|
||||
end
|
|
@ -19,14 +19,18 @@ Salt SSH allows for salt routines to be executed using only SSH for transport
|
|||
Options
|
||||
=======
|
||||
|
||||
.. program:: salt-ssh
|
||||
|
||||
.. include:: _includes/common-options.rst
|
||||
|
||||
.. option:: --hard-crash
|
||||
|
||||
Raise any original exception rather than exiting gracefully. Default: False.
|
||||
|
||||
.. option:: -r, --raw, --raw-shell
|
||||
|
||||
Execute a raw shell command.
|
||||
|
||||
.. option:: --priv
|
||||
|
||||
Specify the SSH private key file to be used for authentication.
|
||||
|
||||
.. option:: --roster
|
||||
|
||||
Define which roster system to use, this defines if a database backend,
|
||||
|
@ -53,38 +57,117 @@ Options
|
|||
the more running process the faster communication should be, default
|
||||
is 25.
|
||||
|
||||
.. option:: --extra-filerefs=EXTRA_FILEREFS
|
||||
|
||||
Pass in extra files to include in the state tarball.
|
||||
|
||||
.. option:: --min-extra-modules=MIN_EXTRA_MODS
|
||||
|
||||
One or comma-separated list of extra Python modulesto be included
|
||||
into Minimal Salt.
|
||||
|
||||
.. option:: --thin-extra-modules=THIN_EXTRA_MODS
|
||||
|
||||
One or comma-separated list of extra Python modulesto be included
|
||||
into Thin Salt.
|
||||
|
||||
.. option:: -v, --verbose
|
||||
|
||||
Turn on command verbosity, display jid.
|
||||
|
||||
.. option:: -s, --static
|
||||
|
||||
Return the data from minions as a group after they all return.
|
||||
|
||||
.. option:: -w, --wipe
|
||||
|
||||
Remove the deployment of the salt files when done executing.
|
||||
|
||||
.. option:: -W, --rand-thin-dir
|
||||
|
||||
Select a random temp dir to deploy on the remote system. The dir
|
||||
will be cleaned after the execution.
|
||||
|
||||
.. option:: -t, --regen-thin, --thin
|
||||
|
||||
Trigger a thin tarball regeneration. This is needed if custom
|
||||
grains/modules/states have been added or updated.
|
||||
|
||||
.. option:: --python2-bin=PYTHON2_BIN
|
||||
|
||||
Path to a python2 binary which has salt installed.
|
||||
|
||||
.. option:: --python3-bin=PYTHON3_BIN
|
||||
|
||||
Path to a python3 binary which has salt installed.
|
||||
|
||||
.. option:: --jid=JID
|
||||
|
||||
Pass a JID to be used instead of generating one.
|
||||
|
||||
Authentication Options
|
||||
----------------------
|
||||
|
||||
.. option:: --priv=SSH_PRIV
|
||||
|
||||
Specify the SSH private key file to be used for authentication.
|
||||
|
||||
.. option:: -i, --ignore-host-keys
|
||||
|
||||
Disables StrictHostKeyChecking to relax acceptance of new and unknown
|
||||
host keys.
|
||||
By default ssh host keys are honored and connections will ask for
|
||||
approval. Use this option to disable StrictHostKeyChecking.
|
||||
|
||||
.. option:: --no-host-keys
|
||||
|
||||
Fully ignores ssh host keys which by default are honored and connections
|
||||
would ask for approval. Useful if the host key of a remote server has
|
||||
would ask for approval. Useful if the host key of a remote server has
|
||||
changed and would still error with --ignore-host-keys.
|
||||
|
||||
.. option:: --user=SSH_USER
|
||||
|
||||
Set the default user to attempt to use when authenticating.
|
||||
|
||||
.. option:: --passwd
|
||||
|
||||
Set the default password to attempt to use when authenticating.
|
||||
|
||||
.. option:: --askpass
|
||||
|
||||
Interactively ask for the SSH password with no echo - avoids password
|
||||
in process args and stored in history.
|
||||
|
||||
.. option:: --key-deploy
|
||||
|
||||
Set this flag to attempt to deploy the authorized ssh key with all
|
||||
minions. This combined with --passwd can make initial deployment of keys
|
||||
very fast and easy.
|
||||
|
||||
.. program:: salt
|
||||
.. option:: --identities-only
|
||||
|
||||
.. include:: _includes/common-options.rst
|
||||
Use the only authentication identity files configured in the ssh_config
|
||||
files. See IdentitiesOnly flag in man ssh_config.
|
||||
|
||||
.. include:: _includes/target-selection-ssh.rst
|
||||
.. option:: --sudo
|
||||
|
||||
Run command via sudo.
|
||||
|
||||
Scan Roster Options
|
||||
-------------------
|
||||
|
||||
.. option:: --scan-ports=SSH_SCAN_PORTS
|
||||
|
||||
Comma-separated list of ports to scan in the scan roster.
|
||||
|
||||
.. option:: --scan-timeout=SSH_SCAN_TIMEOUT
|
||||
|
||||
Scanning socket timeout for the scan roster.
|
||||
|
||||
.. include:: _includes/logging-options.rst
|
||||
.. |logfile| replace:: /var/log/salt/ssh
|
||||
.. |loglevel| replace:: ``warning``
|
||||
|
||||
.. include:: _includes/target-selection-ssh.rst
|
||||
|
||||
.. include:: _includes/output-options.rst
|
||||
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ this.
|
|||
|
||||
# /srv/salt/orch/deploy.sls
|
||||
{% set servers = salt['pillar.get']('servers', 'test') %}
|
||||
{% set master = salt['pillat.get']('master', 'salt') %}
|
||||
{% set master = salt['pillar.get']('master', 'salt') %}
|
||||
create_instance:
|
||||
salt.runner:
|
||||
- name: cloud.profile
|
||||
|
|
|
@ -498,16 +498,16 @@ def tar(options, tarfile, sources=None, dest=None,
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' archive.tar -cjvf /tmp/salt.tar.bz2 {{grains.saltpath}} template=jinja
|
||||
salt '*' archive.tar cjvf /tmp/salt.tar.bz2 {{grains.saltpath}} template=jinja
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Create a tarfile
|
||||
salt '*' archive.tar -cjvf /tmp/tarfile.tar.bz2 /tmp/file_1,/tmp/file_2
|
||||
salt '*' archive.tar cjvf /tmp/tarfile.tar.bz2 /tmp/file_1,/tmp/file_2
|
||||
# Create a tarfile using globbing (2017.7.0 and later)
|
||||
salt '*' archive.tar -cjvf /tmp/tarfile.tar.bz2 '/tmp/file_*'
|
||||
salt '*' archive.tar cjvf /tmp/tarfile.tar.bz2 '/tmp/file_*'
|
||||
# Unpack a tarfile
|
||||
salt '*' archive.tar xf foo.tar dest=/target/directory
|
||||
'''
|
||||
|
|
|
@ -51,6 +51,7 @@ import datetime
|
|||
import logging
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import email.mime.multipart
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -675,11 +676,23 @@ def get_scaling_policy_arn(as_group, scaling_policy_name, region=None,
|
|||
salt '*' boto_asg.get_scaling_policy_arn mygroup mypolicy
|
||||
'''
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
policies = conn.get_all_policies(as_group=as_group)
|
||||
for policy in policies:
|
||||
if policy.name == scaling_policy_name:
|
||||
return policy.policy_arn
|
||||
log.error('Could not convert: {0}'.format(as_group))
|
||||
retries = 30
|
||||
while retries > 0:
|
||||
retries -= 1
|
||||
try:
|
||||
policies = conn.get_all_policies(as_group=as_group)
|
||||
for policy in policies:
|
||||
if policy.name == scaling_policy_name:
|
||||
return policy.policy_arn
|
||||
log.error('Could not convert: {0}'.format(as_group))
|
||||
return None
|
||||
except boto.exception.BotoServerError as e:
|
||||
if e.error_code != 'Throttling':
|
||||
raise
|
||||
log.debug('Throttled by API, will retry in 5 seconds')
|
||||
time.sleep(5)
|
||||
|
||||
log.error('Maximum number of retries exceeded')
|
||||
return None
|
||||
|
||||
|
||||
|
@ -761,11 +774,18 @@ def get_instances(name, lifecycle_state="InService", health_status="Healthy",
|
|||
# get full instance info, so that we can return the attribute
|
||||
instances = ec2_conn.get_only_instances(instance_ids=instance_ids)
|
||||
if attributes:
|
||||
return [[getattr(instance, attr).encode("ascii") for attr in attributes] for instance in instances]
|
||||
return [[_convert_attribute(instance, attr) for attr in attributes] for instance in instances]
|
||||
else:
|
||||
# properly handle case when not all instances have the requested attribute
|
||||
return [getattr(instance, attribute).encode("ascii") for instance in instances if getattr(instance, attribute)]
|
||||
return [getattr(instance, attribute).encode("ascii") for instance in instances]
|
||||
return [_convert_attribute(instance, attribute) for instance in instances if getattr(instance, attribute)]
|
||||
|
||||
|
||||
def _convert_attribute(instance, attribute):
|
||||
if attribute == "tags":
|
||||
tags = dict(getattr(instance, attribute))
|
||||
return {key.encode("utf-8"): value.encode("utf-8") for key, value in six.iteritems(tags)}
|
||||
|
||||
return getattr(instance, attribute).encode("ascii")
|
||||
|
||||
|
||||
def enter_standby(name, instance_ids, should_decrement_desired_capacity=False,
|
||||
|
|
|
@ -910,8 +910,8 @@ def compare_container(first, second, ignore=None):
|
|||
ret.setdefault(conf_dict, {})[item] = {'old': image1, 'new': image2}
|
||||
else:
|
||||
if item == 'Links':
|
||||
val1 = _scrub_links(val1, first)
|
||||
val2 = _scrub_links(val2, second)
|
||||
val1 = sorted(_scrub_links(val1, first))
|
||||
val2 = sorted(_scrub_links(val2, second))
|
||||
if val1 != val2:
|
||||
ret.setdefault(conf_dict, {})[item] = {'old': val1, 'new': val2}
|
||||
# Check for optionally-present items that were in the second container
|
||||
|
@ -933,8 +933,8 @@ def compare_container(first, second, ignore=None):
|
|||
ret.setdefault(conf_dict, {})[item] = {'old': image1, 'new': image2}
|
||||
else:
|
||||
if item == 'Links':
|
||||
val1 = _scrub_links(val1, first)
|
||||
val2 = _scrub_links(val2, second)
|
||||
val1 = sorted(_scrub_links(val1, first))
|
||||
val2 = sorted(_scrub_links(val2, second))
|
||||
if val1 != val2:
|
||||
ret.setdefault(conf_dict, {})[item] = {'old': val1, 'new': val2}
|
||||
return ret
|
||||
|
|
|
@ -164,7 +164,7 @@ def _setup_conn(**kwargs):
|
|||
|
||||
if client_key_file:
|
||||
kubernetes.client.configuration.key_file = client_key_file
|
||||
if client_key:
|
||||
elif client_key:
|
||||
with tempfile.NamedTemporaryFile(prefix='salt-kube-', delete=False) as k:
|
||||
k.write(base64.b64decode(client_key))
|
||||
kubernetes.client.configuration.key_file = k.name
|
||||
|
|
|
@ -9,7 +9,7 @@ Module to provide redis functionality to Salt
|
|||
|
||||
.. code-block:: yaml
|
||||
|
||||
redis.host: 'localhost'
|
||||
redis.host: 'salt'
|
||||
redis.port: 6379
|
||||
redis.db: 0
|
||||
redis.password: None
|
||||
|
|
|
@ -40,6 +40,7 @@ Current known limitations
|
|||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
import io
|
||||
import os
|
||||
import logging
|
||||
|
@ -4082,7 +4083,7 @@ def _write_regpol_data(data_to_write,
|
|||
gpt_ini_data = ''
|
||||
if os.path.exists(gpt_ini_path):
|
||||
with salt.utils.fopen(gpt_ini_path, 'rb') as gpt_file:
|
||||
gpt_ini_data = gpt_file.read()
|
||||
gpt_ini_data = salt.utils.to_str(gpt_file.read())
|
||||
if not _regexSearchRegPolData(r'\[General\]\r\n', gpt_ini_data):
|
||||
gpt_ini_data = '[General]\r\n' + gpt_ini_data
|
||||
if _regexSearchRegPolData(r'{0}='.format(re.escape(gpt_extension)), gpt_ini_data):
|
||||
|
@ -4137,7 +4138,7 @@ def _write_regpol_data(data_to_write,
|
|||
gpt_ini_data[general_location.end():])
|
||||
if gpt_ini_data:
|
||||
with salt.utils.fopen(gpt_ini_path, 'wb') as gpt_file:
|
||||
gpt_file.write(gpt_ini_data)
|
||||
gpt_file.write(salt.utils.to_bytes(gpt_ini_data))
|
||||
except Exception as e:
|
||||
msg = 'An error occurred attempting to write to {0}, the exception was {1}'.format(
|
||||
gpt_ini_path, e)
|
||||
|
@ -5375,7 +5376,7 @@ def set_(computer_policy=None, user_policy=None,
|
|||
_regedits[regedit]['policy']['Registry']['Type'])
|
||||
else:
|
||||
_ret = __salt__['reg.delete_value'](
|
||||
_regedits[regedit]['polic']['Registry']['Hive'],
|
||||
_regedits[regedit]['policy']['Registry']['Hive'],
|
||||
_regedits[regedit]['policy']['Registry']['Path'],
|
||||
_regedits[regedit]['policy']['Registry']['Value'])
|
||||
if not _ret:
|
||||
|
|
|
@ -444,8 +444,9 @@ def stop(name):
|
|||
try:
|
||||
win32serviceutil.StopService(name)
|
||||
except pywintypes.error as exc:
|
||||
raise CommandExecutionError(
|
||||
'Failed To Stop {0}: {1}'.format(name, exc[2]))
|
||||
if exc[0] != 1062:
|
||||
raise CommandExecutionError(
|
||||
'Failed To Stop {0}: {1}'.format(name, exc[2]))
|
||||
|
||||
attempts = 0
|
||||
while info(name)['Status'] in ['Running', 'Stop Pending'] \
|
||||
|
|
|
@ -92,28 +92,31 @@ def halt(timeout=5, in_seconds=False):
|
|||
Halt a running system.
|
||||
|
||||
Args:
|
||||
timeout (int): Number of seconds before halting the system. Default is
|
||||
5 seconds.
|
||||
|
||||
in_seconds (bool): Whether to treat timeout as seconds or minutes.
|
||||
timeout (int):
|
||||
Number of seconds before halting the system. Default is 5 seconds.
|
||||
|
||||
in_seconds (bool):
|
||||
Whether to treat timeout as seconds or minutes.
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' system.halt 5
|
||||
salt '*' system.halt 5 True
|
||||
'''
|
||||
return shutdown(timeout=timeout, in_seconds=in_seconds)
|
||||
|
||||
|
||||
def init(runlevel): # pylint: disable=unused-argument
|
||||
'''
|
||||
Change the system runlevel on sysV compatible systems
|
||||
Change the system runlevel on sysV compatible systems. Not applicable to
|
||||
Windows
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -136,14 +139,18 @@ def poweroff(timeout=5, in_seconds=False):
|
|||
Power off a running system.
|
||||
|
||||
Args:
|
||||
timeout (int): Number of seconds before powering off the system. Default
|
||||
is 5 seconds.
|
||||
|
||||
in_seconds (bool): Whether to treat timeout as seconds or minutes.
|
||||
timeout (int):
|
||||
Number of seconds before powering off the system. Default is 5
|
||||
seconds.
|
||||
|
||||
in_seconds (bool):
|
||||
Whether to treat timeout as seconds or minutes.
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -160,29 +167,35 @@ def reboot(timeout=5, in_seconds=False, wait_for_reboot=False, # pylint: disabl
|
|||
Reboot a running system.
|
||||
|
||||
Args:
|
||||
timeout (int): Number of minutes/seconds before rebooting the system.
|
||||
Minutes vs seconds depends on the value of ``in_seconds``. Default
|
||||
|
||||
timeout (int):
|
||||
The number of minutes/seconds before rebooting the system. Use of
|
||||
minutes or seconds depends on the value of ``in_seconds``. Default
|
||||
is 5 minutes.
|
||||
|
||||
in_seconds (bool): Whether to treat timeout as seconds or minutes.
|
||||
in_seconds (bool):
|
||||
``True`` will cause the ``timeout`` parameter to be in seconds.
|
||||
``False`` will be in minutes. Default is ``False``.
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
wait_for_reboot (bool): Sleeps for timeout + 30 seconds after reboot has
|
||||
been initiated. This may be useful for use in a highstate if a
|
||||
reboot should be performed and the return data of the highstate is
|
||||
not required. If return data is required, consider using the reboot
|
||||
state instead of this module.
|
||||
wait_for_reboot (bool)
|
||||
``True`` will sleep for timeout + 30 seconds after reboot has been
|
||||
initiated. This is useful for use in a highstate. For example, you
|
||||
may have states that you want to apply only after the reboot.
|
||||
Default is ``False``.
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
only_on_pending_reboot (bool): If this is set to True, then the reboot
|
||||
will only proceed if the system reports a pending reboot. To
|
||||
optionally reboot in a highstate, consider using the reboot state
|
||||
instead of this module.
|
||||
only_on_pending_reboot (bool):
|
||||
If this is set to ``True``, then the reboot will only proceed
|
||||
if the system reports a pending reboot. Setting this parameter to
|
||||
``True`` could be useful when calling this function from a final
|
||||
housekeeping state intended to be executed at the end of a state run
|
||||
(using *order: last*). Default is ``False``.
|
||||
|
||||
Returns:
|
||||
bool: True if successful (a reboot will occur), otherwise False
|
||||
bool: ``True`` if successful (a reboot will occur), otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -191,20 +204,16 @@ def reboot(timeout=5, in_seconds=False, wait_for_reboot=False, # pylint: disabl
|
|||
salt '*' system.reboot 5
|
||||
salt '*' system.reboot 5 True
|
||||
|
||||
As example of invoking this function from within a final housekeeping state
|
||||
is as follows:
|
||||
|
||||
Example:
|
||||
Invoking this function from a final housekeeping state:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
final housekeeping:
|
||||
final_housekeeping:
|
||||
module.run:
|
||||
- name: system.reboot
|
||||
- only_on_pending_reboot: True
|
||||
- order: last
|
||||
'''
|
||||
|
||||
ret = shutdown(timeout=timeout, reboot=True, in_seconds=in_seconds,
|
||||
only_on_pending_reboot=only_on_pending_reboot)
|
||||
|
||||
|
@ -221,50 +230,63 @@ def shutdown(message=None, timeout=5, force_close=True, reboot=False, # pylint:
|
|||
Shutdown a running system.
|
||||
|
||||
Args:
|
||||
message (str): A message to display to the user before shutting down.
|
||||
|
||||
timeout (int): The length of time that the shutdown dialog box should be
|
||||
displayed, in seconds. While this dialog box is displayed, the
|
||||
shutdown can be stopped by the shutdown_abort function.
|
||||
message (str):
|
||||
The message to display to the user before shutting down.
|
||||
|
||||
timeout (int):
|
||||
The length of time (in seconds) that the shutdown dialog box should
|
||||
be displayed. While this dialog box is displayed, the shutdown can
|
||||
be aborted using the ``system.shutdown_abort`` function.
|
||||
|
||||
If timeout is not zero, InitiateSystemShutdown displays a dialog box
|
||||
on the specified computer. The dialog box displays the name of the
|
||||
user who called the function, displays the message specified by the
|
||||
lpMessage parameter, and prompts the user to log off. The dialog box
|
||||
beeps when it is created and remains on top of other windows in the
|
||||
system. The dialog box can be moved but not closed. A timer counts
|
||||
down the remaining time before a forced shutdown.
|
||||
user who called the function, the message specified by the lpMessage
|
||||
parameter, and prompts the user to log off. The dialog box beeps
|
||||
when it is created and remains on top of other windows (system
|
||||
modal). The dialog box can be moved but not closed. A timer counts
|
||||
down the remaining time before the shutdown occurs.
|
||||
|
||||
If timeout is zero, the computer shuts down without displaying the
|
||||
dialog box, and the shutdown cannot be stopped by shutdown_abort.
|
||||
If timeout is zero, the computer shuts down immediately without
|
||||
displaying the dialog box and cannot be stopped by
|
||||
``system.shutdown_abort``.
|
||||
|
||||
Default is 5 minutes
|
||||
|
||||
in_seconds (bool): Whether to treat timeout as seconds or minutes.
|
||||
in_seconds (bool):
|
||||
``True`` will cause the ``timeout`` parameter to be in seconds.
|
||||
``False`` will be in minutes. Default is ``False``.
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
force_close (bool): True to force close all open applications. False
|
||||
displays a dialog box instructing the user to close the
|
||||
applications.
|
||||
force_close (bool):
|
||||
``True`` will force close all open applications. ``False`` will
|
||||
display a dialog box instructing the user to close open
|
||||
applications. Default is ``True``.
|
||||
|
||||
reboot (bool): True restarts the computer immediately after shutdown.
|
||||
False caches to disk and safely powers down the system.
|
||||
reboot (bool):
|
||||
``True`` restarts the computer immediately after shutdown. ``False``
|
||||
powers down the system. Default is ``False``.
|
||||
|
||||
only_on_pending_reboot (bool): If this is set to True, then the shutdown
|
||||
will only proceed if the system reports a pending reboot. To
|
||||
optionally shutdown in a highstate, consider using the shutdown
|
||||
state instead of this module.
|
||||
|
||||
only_on_pending_reboot (bool):
|
||||
If ``True`` the shutdown will only proceed if there is a reboot
|
||||
pending. ``False`` will shutdown the system. Default is ``False``.
|
||||
|
||||
Returns:
|
||||
bool: True if successful (a shutdown or reboot will occur), otherwise
|
||||
False
|
||||
bool:
|
||||
``True`` if successful (a shutdown or reboot will occur), otherwise
|
||||
``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' system.shutdown 5
|
||||
salt '*' system.shutdown "System will shutdown in 5 minutes"
|
||||
'''
|
||||
if six.PY2:
|
||||
message = _to_unicode(message)
|
||||
|
@ -294,7 +316,7 @@ def shutdown_hard():
|
|||
Shutdown a running system with no timeout or warning.
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -312,7 +334,7 @@ def shutdown_abort():
|
|||
aborted.
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -337,7 +359,7 @@ def lock():
|
|||
Lock the workstation.
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -353,12 +375,14 @@ def set_computer_name(name):
|
|||
Set the Windows computer name
|
||||
|
||||
Args:
|
||||
name (str): The new name to give the computer. Requires a reboot to take
|
||||
effect.
|
||||
|
||||
name (str):
|
||||
The new name to give the computer. Requires a reboot to take effect.
|
||||
|
||||
Returns:
|
||||
dict: Returns a dictionary containing the old and new names if
|
||||
successful. False if not.
|
||||
dict:
|
||||
Returns a dictionary containing the old and new names if successful.
|
||||
``False`` if not.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -389,7 +413,9 @@ def get_pending_computer_name():
|
|||
error message will be logged to the minion log.
|
||||
|
||||
Returns:
|
||||
str: The pending name if restart is pending, otherwise returns None.
|
||||
str:
|
||||
Returns the pending name if pending restart. Returns ``None`` if not
|
||||
pending restart.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -412,7 +438,7 @@ def get_computer_name():
|
|||
Get the Windows computer name
|
||||
|
||||
Returns:
|
||||
str: Returns the computer name if found. Otherwise returns False
|
||||
str: Returns the computer name if found. Otherwise returns ``False``.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -429,10 +455,12 @@ def set_computer_desc(desc=None):
|
|||
Set the Windows computer description
|
||||
|
||||
Args:
|
||||
desc (str): The computer description
|
||||
|
||||
desc (str):
|
||||
The computer description
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
str: Description if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -475,8 +503,8 @@ def get_system_info():
|
|||
Get system information.
|
||||
|
||||
Returns:
|
||||
dict: Returns a Dictionary containing information about the system to
|
||||
include name, description, version, etc...
|
||||
dict: Dictionary containing information about the system to include
|
||||
name, description, version, etc...
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -529,7 +557,8 @@ def get_computer_desc():
|
|||
Get the Windows computer description
|
||||
|
||||
Returns:
|
||||
str: The computer description if found, otherwise False
|
||||
str: Returns the computer description if found. Otherwise returns
|
||||
``False``.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -546,12 +575,12 @@ get_computer_description = salt.utils.alias_function(get_computer_desc, 'get_com
|
|||
|
||||
def get_hostname():
|
||||
'''
|
||||
.. versionadded:: 2016.3.0
|
||||
|
||||
Get the hostname of the windows minion
|
||||
|
||||
.. versionadded:: 2016.3.0
|
||||
|
||||
Returns:
|
||||
str: The hostname of the windows minion
|
||||
str: Returns the hostname of the windows minion
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -566,16 +595,16 @@ def get_hostname():
|
|||
|
||||
def set_hostname(hostname):
|
||||
'''
|
||||
.. versionadded:: 2016.3.0
|
||||
Set the hostname of the windows minion, requires a restart before this will
|
||||
be updated.
|
||||
|
||||
Set the hostname of the windows minion, requires a restart before this
|
||||
will be updated.
|
||||
.. versionadded:: 2016.3.0
|
||||
|
||||
Args:
|
||||
hostname (str): The hostname to set
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -597,37 +626,41 @@ def join_domain(domain,
|
|||
account_exists=False,
|
||||
restart=False):
|
||||
'''
|
||||
Join a computer to an Active Directory domain. Requires reboot.
|
||||
Join a computer to an Active Directory domain. Requires a reboot.
|
||||
|
||||
Args:
|
||||
domain (str): The domain to which the computer should be joined, e.g.
|
||||
|
||||
domain (str):
|
||||
The domain to which the computer should be joined, e.g.
|
||||
``example.com``
|
||||
|
||||
username (str): Username of an account which is authorized to join
|
||||
computers to the specified domain. Need to be either fully qualified
|
||||
like ``user@domain.tld`` or simply ``user``
|
||||
username (str):
|
||||
Username of an account which is authorized to join computers to the
|
||||
specified domain. Needs to be either fully qualified like
|
||||
``user@domain.tld`` or simply ``user``
|
||||
|
||||
password (str): Password of the specified user
|
||||
password (str):
|
||||
Password of the specified user
|
||||
|
||||
account_ou (str): The DN of the OU below which the account for this
|
||||
computer should be created when joining the domain, e.g.
|
||||
account_ou (str):
|
||||
The DN of the OU below which the account for this computer should be
|
||||
created when joining the domain, e.g.
|
||||
``ou=computers,ou=departm_432,dc=my-company,dc=com``
|
||||
|
||||
account_exists (bool): If set to ``True`` the computer will only join
|
||||
the domain if the account already exists. If set to ``False`` the
|
||||
computer account will be created if it does not exist, otherwise it
|
||||
will use the existing account. Default is False.
|
||||
account_exists (bool):
|
||||
If set to ``True`` the computer will only join the domain if the
|
||||
account already exists. If set to ``False`` the computer account
|
||||
will be created if it does not exist, otherwise it will use the
|
||||
existing account. Default is ``False``
|
||||
|
||||
restart (bool): Restarts the computer after a successful join
|
||||
restart (bool):
|
||||
``True`` will restart the computer after a successful join. Default
|
||||
is ``False``
|
||||
|
||||
.. versionadded:: 2015.8.2/2015.5.7
|
||||
|
||||
Returns:
|
||||
dict: Dictionary if successful
|
||||
|
||||
Raises:
|
||||
CommandExecutionError: Raises an error if _join_domain returns anything
|
||||
other than 0
|
||||
dict: Returns a dictionary if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -741,33 +774,41 @@ def unjoin_domain(username=None,
|
|||
disable=False,
|
||||
restart=False):
|
||||
r'''
|
||||
Unjoin a computer from an Active Directory Domain. Requires restart.
|
||||
Unjoin a computer from an Active Directory Domain. Requires a restart.
|
||||
|
||||
Args:
|
||||
username (str): Username of an account which is authorized to manage
|
||||
computer accounts on the domain. Need to be fully qualified like
|
||||
``user@domain.tld`` or ``domain.tld\user``. If domain not specified,
|
||||
the passed domain will be used. If computer account doesn't need to
|
||||
be disabled, can be None.
|
||||
|
||||
password (str): Password of the specified user
|
||||
username (str):
|
||||
Username of an account which is authorized to manage computer
|
||||
accounts on the domain. Needs to be a fully qualified name like
|
||||
``user@domain.tld`` or ``domain.tld\user``. If the domain is not
|
||||
specified, the passed domain will be used. If the computer account
|
||||
doesn't need to be disabled after the computer is unjoined, this can
|
||||
be ``None``.
|
||||
|
||||
domain (str): The domain from which to unjoin the computer. Can be None.
|
||||
password (str):
|
||||
The password of the specified user
|
||||
|
||||
workgroup (str): The workgroup to join the computer to. Default is
|
||||
``WORKGROUP``
|
||||
domain (str):
|
||||
The domain from which to unjoin the computer. Can be ``None``
|
||||
|
||||
workgroup (str):
|
||||
The workgroup to join the computer to. Default is ``WORKGROUP``
|
||||
|
||||
.. versionadded:: 2015.8.2/2015.5.7
|
||||
|
||||
disable (bool): Disable the computer account in Active Directory. True
|
||||
to disable. Default is False
|
||||
disable (bool):
|
||||
``True`` to disable the computer account in Active Directory.
|
||||
Default is ``False``
|
||||
|
||||
restart (bool): Restart the computer after successful unjoin
|
||||
restart (bool):
|
||||
``True`` will restart the computer after successful unjoin. Default
|
||||
is ``False``
|
||||
|
||||
.. versionadded:: 2015.8.2/2015.5.7
|
||||
|
||||
Returns:
|
||||
dict: Dictionary if successful, otherwise False
|
||||
dict: Returns a dictionary if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -859,15 +900,16 @@ def get_domain_workgroup():
|
|||
|
||||
def _try_parse_datetime(time_str, fmts):
|
||||
'''
|
||||
Attempts to parse the input time_str as a date.
|
||||
A helper function that attempts to parse the input time_str as a date.
|
||||
|
||||
Args:
|
||||
|
||||
time_str (str): A string representing the time
|
||||
|
||||
fmts (list): A list of date format strings
|
||||
|
||||
Returns:
|
||||
datetime: A datetime object if parsed properly, otherwise None
|
||||
datetime: Returns a datetime object if parsed properly, otherwise None
|
||||
'''
|
||||
result = None
|
||||
for fmt in fmts:
|
||||
|
@ -910,7 +952,9 @@ def set_system_time(newtime):
|
|||
Set the system time.
|
||||
|
||||
Args:
|
||||
newtime (str): The time to set. Can be any of the following formats.
|
||||
|
||||
newtime (str):
|
||||
The time to set. Can be any of the following formats:
|
||||
|
||||
- HH:MM:SS AM/PM
|
||||
- HH:MM AM/PM
|
||||
|
@ -918,7 +962,7 @@ def set_system_time(newtime):
|
|||
- HH:MM (24 hour)
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -951,24 +995,16 @@ def set_system_date_time(years=None,
|
|||
system year will be used. (Used by set_system_date and set_system_time)
|
||||
|
||||
Args:
|
||||
|
||||
years (int): Years digit, ie: 2015
|
||||
|
||||
months (int): Months digit: 1 - 12
|
||||
|
||||
days (int): Days digit: 1 - 31
|
||||
|
||||
hours (int): Hours digit: 0 - 23
|
||||
|
||||
minutes (int): Minutes digit: 0 - 59
|
||||
|
||||
seconds (int): Seconds digit: 0 - 59
|
||||
|
||||
Returns:
|
||||
bool: True if successful
|
||||
|
||||
Raises:
|
||||
CommandExecutionError: Raises an error if ``SetLocalTime`` function
|
||||
fails
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1037,7 +1073,7 @@ def get_system_date():
|
|||
Get the Windows system date
|
||||
|
||||
Returns:
|
||||
str: The system date
|
||||
str: Returns the system date
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1054,7 +1090,8 @@ def set_system_date(newdate):
|
|||
Set the Windows system date. Use <mm-dd-yy> format for the date.
|
||||
|
||||
Args:
|
||||
newdate (str): The date to set. Can be any of the following formats:
|
||||
newdate (str):
|
||||
The date to set. Can be any of the following formats
|
||||
|
||||
- YYYY-MM-DD
|
||||
- MM-DD-YYYY
|
||||
|
@ -1063,6 +1100,9 @@ def set_system_date(newdate):
|
|||
- MM/DD/YY
|
||||
- YYYY/MM/DD
|
||||
|
||||
Returns:
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -1087,7 +1127,7 @@ def start_time_service():
|
|||
Start the Windows time service
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False.
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1103,7 +1143,7 @@ def stop_time_service():
|
|||
Stop the Windows time service
|
||||
|
||||
Returns:
|
||||
bool: True if successful, otherwise False
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1122,7 +1162,8 @@ def get_pending_component_servicing():
|
|||
.. versionadded:: 2016.11.0
|
||||
|
||||
Returns:
|
||||
bool: True if a reboot is pending, otherwise False.
|
||||
bool: ``True`` if there are pending Component Based Servicing tasks,
|
||||
otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1146,12 +1187,14 @@ def get_pending_component_servicing():
|
|||
|
||||
def get_pending_domain_join():
|
||||
'''
|
||||
Determine whether there is a pending domain join action that requires a reboot.
|
||||
Determine whether there is a pending domain join action that requires a
|
||||
reboot.
|
||||
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
Returns:
|
||||
bool: True if a reboot is pending, otherwise False.
|
||||
bool: ``True`` if there is a pending domain join action, otherwise
|
||||
``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1193,7 +1236,8 @@ def get_pending_file_rename():
|
|||
.. versionadded:: 2016.11.0
|
||||
|
||||
Returns:
|
||||
bool: True if a reboot is pending, otherwise False.
|
||||
bool: ``True`` if there are pending file rename operations, otherwise
|
||||
``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1228,7 +1272,8 @@ def get_pending_servermanager():
|
|||
.. versionadded:: 2016.11.0
|
||||
|
||||
Returns:
|
||||
bool: True if a reboot is pending, otherwise False.
|
||||
bool: ``True`` if there are pending Server Manager tasks, otherwise
|
||||
``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1265,7 +1310,7 @@ def get_pending_update():
|
|||
.. versionadded:: 2016.11.0
|
||||
|
||||
Returns:
|
||||
bool: True if a reboot is pending, otherwise False.
|
||||
bool: ``True`` if there are pending updates, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1305,14 +1350,14 @@ def set_reboot_required_witnessed():
|
|||
current boot session. Also, in the scope of this key, the name *'Reboot
|
||||
required'* will be assigned the value of *1*.
|
||||
|
||||
(For the time being, this this function is being used whenever an install
|
||||
completes with exit code 3010 and this usage can be extended where
|
||||
appropriate in the future.)
|
||||
For the time being, this function is being used whenever an install
|
||||
completes with exit code 3010 and can be extended where appropriate in the
|
||||
future.
|
||||
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
Returns:
|
||||
bool: True if registry entry set successfuly, otherwise False.
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1330,16 +1375,18 @@ def set_reboot_required_witnessed():
|
|||
|
||||
def get_reboot_required_witnessed():
|
||||
'''
|
||||
This tells us if, at any time during the current boot session the salt
|
||||
minion witnessed an event indicating that a reboot is required. (For the
|
||||
time being, this function will return True if an install completed with exit
|
||||
code 3010 during the current boot session and this usage can be extended
|
||||
where appropriate in the future)
|
||||
Determine if at any time during the current boot session the salt minion
|
||||
witnessed an event indicating that a reboot is required.
|
||||
|
||||
This function will return ``True`` if an install completed with exit
|
||||
code 3010 during the current boot session and can be extended where
|
||||
appropriate in the future.
|
||||
|
||||
.. versionadded:: 2016.11.0
|
||||
|
||||
Returns:
|
||||
bool: True if reboot required, otherwise False.
|
||||
bool: ``True`` if the ``Requires reboot`` registry flag is set to ``1``,
|
||||
otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1361,7 +1408,7 @@ def get_pending_reboot():
|
|||
.. versionadded:: 2016.11.0
|
||||
|
||||
Returns:
|
||||
bool: True if pending reboot, otherwise False.
|
||||
bool: ``True`` if the system is pending reboot, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
|
|
@ -23,7 +23,14 @@ def output(ret, bar, **kwargs): # pylint: disable=unused-argument
|
|||
Update the progress bar
|
||||
'''
|
||||
if 'return_count' in ret:
|
||||
bar.update(ret['return_count'])
|
||||
val = ret['return_count']
|
||||
# Avoid to fail if targets are behind a syndic. In this case actual return count will be
|
||||
# higher than targeted by MoM itself.
|
||||
# TODO: implement a way to get the proper target minions count and remove this workaround.
|
||||
# Details are in #44239.
|
||||
if val > bar.maxval:
|
||||
bar.maxval = val
|
||||
bar.update(val)
|
||||
return ''
|
||||
|
||||
|
||||
|
|
|
@ -71,6 +71,12 @@ def orchestrate(mods,
|
|||
)
|
||||
__opts__['file_client'] = 'local'
|
||||
minion = salt.minion.MasterMinion(__opts__)
|
||||
|
||||
if pillarenv is None and 'pillarenv' in __opts__:
|
||||
pillarenv = __opts__['pillarenv']
|
||||
if saltenv is None and 'saltenv' in __opts__:
|
||||
saltenv = __opts__['saltenv']
|
||||
|
||||
running = minion.functions['state.sls'](
|
||||
mods,
|
||||
test,
|
||||
|
|
|
@ -300,7 +300,7 @@ def present(name,
|
|||
|
||||
identifier
|
||||
Custom-defined identifier for tracking the cron line for future crontab
|
||||
edits. This defaults to the state id
|
||||
edits. This defaults to the state name
|
||||
|
||||
special
|
||||
A special keyword to specify periodicity (eg. @reboot, @hourly...).
|
||||
|
@ -387,7 +387,7 @@ def absent(name,
|
|||
|
||||
identifier
|
||||
Custom-defined identifier for tracking the cron line for future crontab
|
||||
edits. This defaults to the state id
|
||||
edits. This defaults to the state name
|
||||
|
||||
special
|
||||
The special keyword used in the job (eg. @reboot, @hourly...).
|
||||
|
|
|
@ -2855,6 +2855,7 @@ def directory(name,
|
|||
if __opts__['test']:
|
||||
ret['result'] = presult
|
||||
ret['comment'] = pcomment
|
||||
ret['changes'] = ret['pchanges']
|
||||
return ret
|
||||
|
||||
if not os.path.isdir(name):
|
||||
|
|
|
@ -1330,10 +1330,14 @@ def fopen(*args, **kwargs):
|
|||
if len(args) > 1:
|
||||
args = list(args)
|
||||
if 'b' not in args[1]:
|
||||
args[1] += 'b'
|
||||
elif kwargs.get('mode', None):
|
||||
args[1] = args[1].replace('t', 'b')
|
||||
if 'b' not in args[1]:
|
||||
args[1] += 'b'
|
||||
elif kwargs.get('mode'):
|
||||
if 'b' not in kwargs['mode']:
|
||||
kwargs['mode'] += 'b'
|
||||
kwargs['mode'] = kwargs['mode'].replace('t', 'b')
|
||||
if 'b' not in kwargs['mode']:
|
||||
kwargs['mode'] += 'b'
|
||||
else:
|
||||
# the default is to read
|
||||
kwargs['mode'] = 'rb'
|
||||
|
|
|
@ -44,7 +44,9 @@ def guess_archive_type(name):
|
|||
Guess an archive type (tar, zip, or rar) by its file extension
|
||||
'''
|
||||
name = name.lower()
|
||||
for ending in ('tar', 'tar.gz', 'tar.bz2', 'tar.xz', 'tgz', 'tbz2', 'txz',
|
||||
for ending in ('tar', 'tar.gz', 'tgz',
|
||||
'tar.bz2', 'tbz2', 'tbz',
|
||||
'tar.xz', 'txz',
|
||||
'tar.lzma', 'tlz'):
|
||||
if name.endswith('.' + ending):
|
||||
return 'tar'
|
||||
|
|
|
@ -439,7 +439,7 @@ class GitProvider(object):
|
|||
return root_dir
|
||||
log.error(
|
||||
'Root path \'%s\' not present in %s remote \'%s\', '
|
||||
'skipping.', self.root, self.role, self.id
|
||||
'skipping.', self.root(), self.role, self.id
|
||||
)
|
||||
return None
|
||||
|
||||
|
|
|
@ -800,7 +800,10 @@ class TestDaemon(object):
|
|||
|
||||
# Set up config options that require internal data
|
||||
master_opts['pillar_roots'] = syndic_master_opts['pillar_roots'] = {
|
||||
'base': [os.path.join(FILES, 'pillar', 'base')]
|
||||
'base': [
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE,
|
||||
os.path.join(FILES, 'pillar', 'base'),
|
||||
]
|
||||
}
|
||||
master_opts['file_roots'] = syndic_master_opts['file_roots'] = {
|
||||
'base': [
|
||||
|
@ -976,6 +979,7 @@ class TestDaemon(object):
|
|||
sub_minion_opts['sock_dir'],
|
||||
minion_opts['sock_dir'],
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE,
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE,
|
||||
TMP,
|
||||
],
|
||||
|
@ -1087,7 +1091,8 @@ class TestDaemon(object):
|
|||
os.chmod(path, stat.S_IRWXU)
|
||||
func(path)
|
||||
|
||||
for dirname in (TMP, RUNTIME_VARS.TMP_STATE_TREE, RUNTIME_VARS.TMP_PRODENV_STATE_TREE):
|
||||
for dirname in (TMP, RUNTIME_VARS.TMP_STATE_TREE,
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE, RUNTIME_VARS.TMP_PRODENV_STATE_TREE):
|
||||
if os.path.isdir(dirname):
|
||||
shutil.rmtree(dirname, onerror=remove_readonly)
|
||||
|
||||
|
|
|
@ -5,10 +5,16 @@ Integration tests for the saltutil module.
|
|||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import time
|
||||
import textwrap
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.paths import TMP_PILLAR_TREE
|
||||
|
||||
# Import Salt Libs
|
||||
import salt.utils
|
||||
|
||||
|
||||
class SaltUtilModuleTest(ModuleCase):
|
||||
|
@ -153,3 +159,38 @@ class SaltUtilSyncModuleTest(ModuleCase):
|
|||
ret = self.run_function('saltutil.sync_all', extmod_whitelist={'modules': ['runtests_decorators']},
|
||||
extmod_blacklist={'modules': ['runtests_decorators']})
|
||||
self.assertEqual(ret, expected_return)
|
||||
|
||||
|
||||
class SaltUtilSyncPillarTest(ModuleCase):
|
||||
'''
|
||||
Testcase for the saltutil sync pillar module
|
||||
'''
|
||||
|
||||
def test_pillar_refresh(self):
|
||||
'''
|
||||
test pillar refresh module
|
||||
'''
|
||||
pillar_key = 'itworked'
|
||||
|
||||
pre_pillar = self.run_function('pillar.raw')
|
||||
self.assertNotIn(pillar_key, pre_pillar.get(pillar_key, 'didnotwork'))
|
||||
|
||||
with salt.utils.fopen(os.path.join(TMP_PILLAR_TREE, 'add_pillar.sls'), 'w') as fp:
|
||||
fp.write('{0}: itworked'.format(pillar_key))
|
||||
|
||||
with salt.utils.fopen(os.path.join(TMP_PILLAR_TREE, 'top.sls'), 'w') as fp:
|
||||
fp.write(textwrap.dedent('''\
|
||||
base:
|
||||
'*':
|
||||
- add_pillar
|
||||
'''))
|
||||
|
||||
pillar_refresh = self.run_function('saltutil.refresh_pillar')
|
||||
wait = self.run_function('test.sleep', [1])
|
||||
|
||||
post_pillar = self.run_function('pillar.raw')
|
||||
self.assertIn(pillar_key, post_pillar.get(pillar_key, 'didnotwork'))
|
||||
|
||||
def tearDown(self):
|
||||
for filename in os.listdir(TMP_PILLAR_TREE):
|
||||
os.remove(os.path.join(TMP_PILLAR_TREE, filename))
|
||||
|
|
50
tests/integration/modules/test_service.py
Normal file
50
tests/integration/modules/test_service.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.helpers import destructiveTest
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils
|
||||
|
||||
|
||||
@destructiveTest
|
||||
class ServiceModuleTest(ModuleCase):
|
||||
'''
|
||||
Module testing the service module
|
||||
'''
|
||||
def setUp(self):
|
||||
self.service_name = 'cron'
|
||||
cmd_name = 'crontab'
|
||||
os_family = self.run_function('grains.get', ['os_family'])
|
||||
if os_family == 'RedHat':
|
||||
self.service_name = 'crond'
|
||||
elif os_family == 'Arch':
|
||||
self.service_name = 'systemd-journald'
|
||||
cmd_name = 'systemctl'
|
||||
|
||||
if salt.utils.which(cmd_name) is None:
|
||||
self.skipTest('{0} is not installed'.format(cmd_name))
|
||||
|
||||
def test_service_status_running(self):
|
||||
'''
|
||||
test service.status execution module
|
||||
when service is running
|
||||
'''
|
||||
start_service = self.run_function('service.start', [self.service_name])
|
||||
|
||||
check_service = self.run_function('service.status', [self.service_name])
|
||||
self.assertTrue(check_service)
|
||||
|
||||
def test_service_status_dead(self):
|
||||
'''
|
||||
test service.status execution module
|
||||
when service is dead
|
||||
'''
|
||||
stop_service = self.run_function('service.stop', [self.service_name])
|
||||
|
||||
check_service = self.run_function('service.status', [self.service_name])
|
||||
self.assertFalse(check_service)
|
|
@ -7,13 +7,17 @@ from __future__ import absolute_import
|
|||
import os
|
||||
import shutil
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.case import SPMCase
|
||||
from tests.support.case import SPMCase, ModuleCase
|
||||
from tests.support.helpers import destructiveTest
|
||||
from tests.support.unit import skipIf
|
||||
|
||||
|
||||
@destructiveTest
|
||||
class SPMBuildTest(SPMCase):
|
||||
class SPMBuildTest(SPMCase, ModuleCase):
|
||||
'''
|
||||
Validate the spm build command
|
||||
'''
|
||||
|
@ -32,5 +36,50 @@ class SPMBuildTest(SPMCase):
|
|||
# Make sure formula path dir is created
|
||||
self.assertTrue(os.path.isdir(self.config['formula_path']))
|
||||
|
||||
@skipIf(salt.utils.which('fallocate') is None, 'fallocate not installed')
|
||||
def test_spm_build_big_file(self):
|
||||
'''
|
||||
test spm build with a big file
|
||||
'''
|
||||
# check to make sure there is enough space to run this test
|
||||
check_space = self.run_function('status.diskusage', ['/'])
|
||||
space = check_space['/']['available']
|
||||
if space < 2000000:
|
||||
self.skipTest('Not enough space on host to run this test')
|
||||
|
||||
big_file = self.run_function('cmd.run',
|
||||
['fallocate -l 1G {0}'.format(os.path.join(self.formula_sls_dir,
|
||||
'bigfile.txt'))])
|
||||
build_spm = self.run_spm('build', self.config, self.formula_dir)
|
||||
spm_file = os.path.join(self.config['spm_build_dir'], 'apache-201506-2.spm')
|
||||
install = self.run_spm('install', self.config, spm_file)
|
||||
|
||||
get_files = self.run_spm('files', self.config, 'apache')
|
||||
|
||||
files = ['apache.sls', 'bigfile.txt']
|
||||
for sls in files:
|
||||
self.assertIn(sls, ' '.join(get_files))
|
||||
|
||||
def test_spm_build_exclude(self):
|
||||
'''
|
||||
test spm build while excluding directory
|
||||
'''
|
||||
git_dir = os.path.join(self.formula_sls_dir, '.git')
|
||||
os.makedirs(git_dir)
|
||||
files = ['donotbuild1', 'donotbuild2', 'donotbuild3']
|
||||
|
||||
for git_file in files:
|
||||
with salt.utils.fopen(os.path.join(git_dir, git_file), 'w') as fp:
|
||||
fp.write('Please do not include me in build')
|
||||
|
||||
build_spm = self.run_spm('build', self.config, self.formula_dir)
|
||||
spm_file = os.path.join(self.config['spm_build_dir'], 'apache-201506-2.spm')
|
||||
install = self.run_spm('install', self.config, spm_file)
|
||||
|
||||
get_files = self.run_spm('files', self.config, 'apache')
|
||||
|
||||
for git_file in files:
|
||||
self.assertNotIn(git_file, ' '.join(get_files))
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self._tmp_spm)
|
||||
|
|
45
tests/integration/spm/test_remove.py
Normal file
45
tests/integration/spm/test_remove.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Tests for the spm remove utility
|
||||
'''
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.case import SPMCase
|
||||
from tests.support.helpers import destructiveTest
|
||||
|
||||
|
||||
@destructiveTest
|
||||
class SPMRemoveTest(SPMCase):
|
||||
'''
|
||||
Validate the spm remove command
|
||||
'''
|
||||
def setUp(self):
|
||||
self.config = self._spm_config()
|
||||
self._spm_build_files(self.config)
|
||||
|
||||
def test_spm_remove(self):
|
||||
'''
|
||||
test spm remove from an inital repo install
|
||||
'''
|
||||
# first install apache package
|
||||
self._spm_create_update_repo(self.config)
|
||||
install = self.run_spm('install', self.config, 'apache')
|
||||
|
||||
sls = os.path.join(self.config['formula_path'], 'apache', 'apache.sls')
|
||||
|
||||
self.assertTrue(os.path.exists(sls))
|
||||
|
||||
#now remove an make sure file is removed
|
||||
remove = self.run_spm('remove', self.config, 'apache')
|
||||
sls = os.path.join(self.config['formula_path'], 'apache', 'apache.sls')
|
||||
|
||||
self.assertFalse(os.path.exists(sls))
|
||||
|
||||
self.assertIn('... removing apache', remove)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self._tmp_spm)
|
|
@ -626,7 +626,7 @@ class SPMCase(TestCase, AdaptedConfigurationTestCaseMixin):
|
|||
'spm_repos_config': os.path.join(self._tmp_spm, 'etc', 'spm.repos'),
|
||||
'spm_cache_dir': os.path.join(self._tmp_spm, 'cache'),
|
||||
'spm_build_dir': os.path.join(self._tmp_spm, 'build'),
|
||||
'spm_build_exclude': ['.git'],
|
||||
'spm_build_exclude': ['apache/.git'],
|
||||
'spm_db_provider': 'sqlite3',
|
||||
'spm_files_provider': 'local',
|
||||
'spm_db': os.path.join(self._tmp_spm, 'packages.db'),
|
||||
|
|
68
tests/support/copyartifacts.py
Normal file
68
tests/support/copyartifacts.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Script for copying back xml junit files from tests
|
||||
'''
|
||||
from __future__ import absolute_import, print_function
|
||||
import argparse # pylint: disable=minimum-python-version
|
||||
import os
|
||||
import paramiko
|
||||
import subprocess
|
||||
import yaml
|
||||
|
||||
|
||||
class DownloadArtifacts(object):
|
||||
def __init__(self, instance, artifacts):
|
||||
self.instance = instance
|
||||
self.artifacts = artifacts
|
||||
self.client = self.setup_transport()
|
||||
|
||||
def setup_transport(self):
|
||||
# pylint: disable=minimum-python-version
|
||||
config = yaml.load(subprocess.check_output(['bundle', 'exec', 'kitchen', 'diagnose', self.instance]))
|
||||
# pylint: enable=minimum-python-version
|
||||
state = config['instances'][self.instance]['state_file']
|
||||
tport = config['instances'][self.instance]['transport']
|
||||
transport = paramiko.Transport((
|
||||
state['hostname'],
|
||||
state.get('port', tport.get('port', 22))
|
||||
))
|
||||
pkey = paramiko.rsakey.RSAKey(
|
||||
filename=state.get('ssh_key', tport.get('ssh_key', '~/.ssh/id_rsa'))
|
||||
)
|
||||
transport.connect(
|
||||
username=state.get('username', tport.get('username', 'root')),
|
||||
pkey=pkey
|
||||
)
|
||||
return paramiko.SFTPClient.from_transport(transport)
|
||||
|
||||
def download(self):
|
||||
for remote, local in self.artifacts:
|
||||
if remote.endswith('/'):
|
||||
for fxml in self.client.listdir(remote):
|
||||
self._do_download(os.path.join(remote, fxml), os.path.join(local, os.path.basename(fxml)))
|
||||
else:
|
||||
self._do_download(remote, os.path.join(local, os.path.basename(remote)))
|
||||
|
||||
def _do_download(self, remote, local):
|
||||
print('Copying from {0} to {1}'.format(remote, local))
|
||||
self.client.get(remote, local)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Jenkins Artifact Download Helper')
|
||||
parser.add_argument(
|
||||
'--instance',
|
||||
required=True,
|
||||
action='store',
|
||||
help='Instance on Test Kitchen to pull from',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--download-artifacts',
|
||||
dest='artifacts',
|
||||
nargs=2,
|
||||
action='append',
|
||||
metavar=('REMOTE_PATH', 'LOCAL_PATH'),
|
||||
help='Download remote artifacts',
|
||||
)
|
||||
args = parser.parse_args()
|
||||
downloader = DownloadArtifacts(args.instance, args.artifacts)
|
||||
downloader.download()
|
|
@ -52,6 +52,7 @@ PYEXEC = 'python{0}.{1}'.format(*sys.version_info)
|
|||
MOCKBIN = os.path.join(INTEGRATION_TEST_DIR, 'mockbin')
|
||||
SCRIPT_DIR = os.path.join(CODE_DIR, 'scripts')
|
||||
TMP_STATE_TREE = os.path.join(SYS_TMP_DIR, 'salt-temp-state-tree')
|
||||
TMP_PILLAR_TREE = os.path.join(SYS_TMP_DIR, 'salt-temp-pillar-tree')
|
||||
TMP_PRODENV_STATE_TREE = os.path.join(SYS_TMP_DIR, 'salt-temp-prodenv-state-tree')
|
||||
TMP_CONF_DIR = os.path.join(TMP, 'config')
|
||||
TMP_SUB_MINION_CONF_DIR = os.path.join(TMP_CONF_DIR, 'sub-minion')
|
||||
|
|
|
@ -215,6 +215,7 @@ RUNTIME_VARS = RuntimeVars(
|
|||
TMP_SYNDIC_MINION_CONF_DIR=paths.TMP_SYNDIC_MINION_CONF_DIR,
|
||||
TMP_SCRIPT_DIR=paths.TMP_SCRIPT_DIR,
|
||||
TMP_STATE_TREE=paths.TMP_STATE_TREE,
|
||||
TMP_PILLAR_TREE=paths.TMP_PILLAR_TREE,
|
||||
TMP_PRODENV_STATE_TREE=paths.TMP_PRODENV_STATE_TREE,
|
||||
RUNNING_TESTS_USER=RUNNING_TESTS_USER,
|
||||
RUNTIME_CONFIGS={}
|
||||
|
|
|
@ -814,7 +814,8 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
ret.update({
|
||||
'comment': comt,
|
||||
'result': None,
|
||||
'pchanges': p_chg
|
||||
'pchanges': p_chg,
|
||||
'changes': {'/etc/grub.conf': {'directory': 'new'}}
|
||||
})
|
||||
self.assertDictEqual(filestate.directory(name,
|
||||
user=user,
|
||||
|
@ -825,7 +826,7 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.object(os.path, 'isdir', mock_f):
|
||||
comt = ('No directory to create {0} in'
|
||||
.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
ret.update({'comment': comt, 'result': False, 'changes': {}})
|
||||
self.assertDictEqual(filestate.directory
|
||||
(name, user=user, group=group),
|
||||
ret)
|
||||
|
|
|
@ -313,21 +313,21 @@ class PyDSLRendererTestCase(CommonTestCaseBoilerplate):
|
|||
- cwd: /
|
||||
.Y:
|
||||
cmd.run:
|
||||
- name: echo Y >> {1}
|
||||
- name: echo Y >> {0}
|
||||
- cwd: /
|
||||
.Z:
|
||||
cmd.run:
|
||||
- name: echo Z >> {2}
|
||||
- name: echo Z >> {0}
|
||||
- cwd: /
|
||||
'''.format(output, output, output)))
|
||||
'''.format(output.replace('\\', '/'))))
|
||||
write_to(os.path.join(dirpath, 'yyy.sls'), textwrap.dedent('''\
|
||||
#!pydsl|stateconf -ps
|
||||
|
||||
__pydsl__.set(ordered=True)
|
||||
state('.D').cmd.run('echo D >> {0}', cwd='/')
|
||||
state('.E').cmd.run('echo E >> {1}', cwd='/')
|
||||
state('.F').cmd.run('echo F >> {2}', cwd='/')
|
||||
'''.format(output, output, output)))
|
||||
state('.E').cmd.run('echo E >> {0}', cwd='/')
|
||||
state('.F').cmd.run('echo F >> {0}', cwd='/')
|
||||
'''.format(output.replace('\\', '/'))))
|
||||
|
||||
write_to(os.path.join(dirpath, 'aaa.sls'), textwrap.dedent('''\
|
||||
#!pydsl|stateconf -ps
|
||||
|
@ -343,9 +343,9 @@ class PyDSLRendererTestCase(CommonTestCaseBoilerplate):
|
|||
__pydsl__.set(ordered=True)
|
||||
|
||||
state('.A').cmd.run('echo A >> {0}', cwd='/')
|
||||
state('.B').cmd.run('echo B >> {1}', cwd='/')
|
||||
state('.C').cmd.run('echo C >> {2}', cwd='/')
|
||||
'''.format(output, output, output)))
|
||||
state('.B').cmd.run('echo B >> {0}', cwd='/')
|
||||
state('.C').cmd.run('echo C >> {0}', cwd='/')
|
||||
'''.format(output.replace('\\', '/'))))
|
||||
|
||||
self.state_highstate({'base': ['aaa']}, dirpath)
|
||||
with salt.utils.fopen(output, 'r') as f:
|
||||
|
@ -365,26 +365,29 @@ class PyDSLRendererTestCase(CommonTestCaseBoilerplate):
|
|||
)
|
||||
)
|
||||
try:
|
||||
# The Windows shell will include any spaces before the redirect
|
||||
# in the text that is redirected.
|
||||
# For example: echo hello > test.txt will contain "hello "
|
||||
write_to(os.path.join(dirpath, 'aaa.sls'), textwrap.dedent('''\
|
||||
#!pydsl
|
||||
|
||||
__pydsl__.set(ordered=True)
|
||||
A = state('A')
|
||||
A.cmd.run('echo hehe > {0}/zzz.txt', cwd='/')
|
||||
A.file.managed('{1}/yyy.txt', source='salt://zzz.txt')
|
||||
A.cmd.run('echo hehe>{0}/zzz.txt', cwd='/')
|
||||
A.file.managed('{0}/yyy.txt', source='salt://zzz.txt')
|
||||
A()
|
||||
A()
|
||||
|
||||
state().cmd.run('echo hoho >> {2}/yyy.txt', cwd='/')
|
||||
state().cmd.run('echo hoho>>{0}/yyy.txt', cwd='/')
|
||||
|
||||
A.file.managed('{3}/xxx.txt', source='salt://zzz.txt')
|
||||
A.file.managed('{0}/xxx.txt', source='salt://zzz.txt')
|
||||
A()
|
||||
'''.format(dirpath, dirpath, dirpath, dirpath)))
|
||||
'''.format(dirpath.replace('\\', '/'))))
|
||||
self.state_highstate({'base': ['aaa']}, dirpath)
|
||||
with salt.utils.fopen(os.path.join(dirpath, 'yyy.txt'), 'rt') as f:
|
||||
self.assertEqual(f.read(), 'hehe\nhoho\n')
|
||||
self.assertEqual(f.read(), 'hehe' + os.linesep + 'hoho' + os.linesep)
|
||||
with salt.utils.fopen(os.path.join(dirpath, 'xxx.txt'), 'rt') as f:
|
||||
self.assertEqual(f.read(), 'hehe\n')
|
||||
self.assertEqual(f.read(), 'hehe' + os.linesep)
|
||||
finally:
|
||||
shutil.rmtree(dirpath, ignore_errors=True)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue