-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Port #51625 to master #56953
Closed
alexey-zhukovin
wants to merge
4
commits into
saltstack:master
from
alexey-zhukovin:master-port-51625
Closed
Port #51625 to master #56953
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -433,6 +433,7 @@ execution modules | |
smbios | ||
smf_service | ||
smtp | ||
snap | ||
snapper | ||
solaris_fmadm | ||
solaris_group | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
================= | ||
salt.modules.snap | ||
================= | ||
|
||
.. automodule:: salt.modules.snap | ||
:members: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -287,6 +287,7 @@ state modules | |
slack | ||
smartos | ||
smtp | ||
snap | ||
snapper | ||
solrcloud | ||
splunk | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
================ | ||
salt.states.snap | ||
================ | ||
|
||
.. automodule:: salt.states.snap | ||
:members: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Manage snap packages via Salt | ||
|
||
:depends: snapd for distribution | ||
|
||
""" | ||
|
||
from __future__ import absolute_import, print_function, unicode_literals | ||
|
||
import subprocess | ||
|
||
import salt.utils.path | ||
|
||
SNAP_BINARY_NAME = "snap" | ||
|
||
__virtualname__ = "snap" | ||
|
||
|
||
def __virtual__(): | ||
if salt.utils.path.which("snap"): | ||
return __virtualname__ | ||
|
||
return ( | ||
False, | ||
'The snap execution module cannot be loaded: the "snap" binary is not in the path.', | ||
) | ||
|
||
|
||
def install(pkg, channel=None, refresh=False): | ||
""" | ||
Install the specified snap package from the specified channel. | ||
Returns a dictionary of "result" and "output". | ||
|
||
pkg | ||
The snap package name | ||
|
||
channel | ||
Optional. The snap channel to install from, eg "beta" | ||
|
||
refresh : False | ||
If True, use "snap refresh" instead of "snap install". | ||
This allows changing the channel of a previously installed package. | ||
""" | ||
args = [] | ||
ret = {"result": None, "output": ""} | ||
|
||
if refresh: | ||
cmd = "refresh" | ||
else: | ||
cmd = "install" | ||
|
||
if channel: | ||
args.append("--channel=" + channel) | ||
|
||
try: | ||
# Try to run it, merging stderr into output | ||
ret["output"] = subprocess.check_output( | ||
[SNAP_BINARY_NAME, cmd, pkg] + args, stderr=subprocess.STDOUT | ||
) | ||
ret["result"] = True | ||
except subprocess.CalledProcessError as e: | ||
ret["output"] = e.output | ||
ret["result"] = False | ||
|
||
return ret | ||
|
||
|
||
def is_installed(pkg): | ||
""" | ||
Returns True if there is any version of the specified package installed. | ||
|
||
pkg | ||
The package name | ||
""" | ||
return bool(versions_installed(pkg)) | ||
|
||
|
||
def remove(pkg): | ||
""" | ||
Remove the specified snap package. Returns a dictionary of "result" and "output". | ||
|
||
pkg | ||
The package name | ||
""" | ||
ret = {"result": None, "output": ""} | ||
try: | ||
ret["output"] = subprocess.check_output([SNAP_BINARY_NAME, "remove", pkg]) | ||
ret["result"] = True | ||
except subprocess.CalledProcessError as e: | ||
ret["output"] = e.output | ||
ret["result"] = False | ||
|
||
|
||
# Parse 'snap list' into a dict | ||
def versions_installed(pkg): | ||
""" | ||
Query which version(s) of the specified snap package are installed. | ||
Returns a list of 0 or more dictionaries. | ||
|
||
pkg | ||
The package name | ||
""" | ||
|
||
try: | ||
# Try to run it, merging stderr into output | ||
output = subprocess.check_output( | ||
[SNAP_BINARY_NAME, "list", pkg], stderr=subprocess.STDOUT | ||
) | ||
except subprocess.CalledProcessError: | ||
return [] | ||
|
||
lines = output.splitlines()[1:] | ||
ret = [] | ||
for item in lines: | ||
# If fields contain spaces this will break. | ||
i = item.split() | ||
# Ignore 'Notes' field | ||
ret.append( | ||
{ | ||
"name": i[0], | ||
"version": i[1], | ||
"rev": i[2], | ||
"tracking": i[3], | ||
"publisher": i[4], | ||
} | ||
) | ||
|
||
return ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Management of snap packages | ||
=============================================== | ||
""" | ||
from __future__ import absolute_import, print_function, unicode_literals | ||
|
||
import salt.utils.path | ||
|
||
__virtualname__ = "snap" | ||
|
||
|
||
def __virtual__(): | ||
if salt.utils.path.which("snap"): | ||
return __virtualname__ | ||
|
||
return ( | ||
False, | ||
'The snap state module cannot be loaded: the "snap" binary is not in the path.', | ||
) | ||
|
||
|
||
def installed(name, channel=None): | ||
""" | ||
Ensure that the named snap package is installed | ||
|
||
name | ||
The snap package | ||
|
||
channel | ||
Optional. The channel to install the package from. | ||
""" | ||
ret = {"name": name, "changes": {}, "pchanges": {}, "result": None, "comment": ""} | ||
|
||
old = __salt__["snap.versions_installed"](name) | ||
if not old: | ||
if __opts__["test"]: | ||
ret["comment"] = 'Package "{0}" would have been installed'.format(name) | ||
ret["pchanges"]["new"] = name | ||
ret["pchanges"]["old"] = None | ||
ret["result"] = None | ||
return ret | ||
|
||
install = __salt__["snap.install"](name, channel=channel) | ||
if install["result"]: | ||
ret["comment"] = 'Package "{0}" was installed'.format(name) | ||
ret["changes"]["new"] = name | ||
ret["changes"]["old"] = None | ||
ret["result"] = True | ||
return ret | ||
|
||
ret["comment"] = 'Package "{0}" failed to install'.format(name) | ||
ret["comment"] += "\noutput:\n" + install["output"] | ||
ret["result"] = False | ||
return ret | ||
|
||
# Currently snap always returns only one line? | ||
old_channel = old[0]["tracking"] | ||
if old_channel != channel and channel is not None: | ||
if __opts__["test"]: | ||
ret[ | ||
"comment" | ||
] = 'Package "{0}" would have been switched to channel {1}'.format( | ||
name, channel | ||
) | ||
ret["pchanges"]["old_channel"] = old_channel | ||
ret["pchanges"]["new_channel"] = channel | ||
ret["result"] = None | ||
return ret | ||
|
||
refresh = __salt__["snap.install"](name, channel=channel, refresh=True) | ||
if refresh["result"]: | ||
ret["comment"] = 'Package "{0}" was switched to channel {1}'.format( | ||
name, channel | ||
) | ||
ret["pchanges"]["old_channel"] = old_channel | ||
ret["pchanges"]["new_channel"] = channel | ||
ret["result"] = True | ||
return ret | ||
|
||
ret["comment"] = 'Failed to switch Package "{0}" to channel {1}'.format( | ||
name, channel | ||
) | ||
ret["comment"] += "\noutput:\n" + install["output"] | ||
ret["result"] = False | ||
return ret | ||
|
||
ret["comment"] = 'Package "{0}" is already installed'.format(name) | ||
if __opts__["test"]: | ||
ret["result"] = None | ||
return ret | ||
|
||
ret["result"] = True | ||
return ret | ||
|
||
|
||
def removed(name): | ||
""" | ||
Ensure that the named snap package is not installed | ||
|
||
name | ||
The snap package | ||
""" | ||
|
||
ret = {"name": name, "changes": {}, "pchanges": {}, "result": None, "comment": ""} | ||
|
||
old = __salt__["snap.versions_installed"](name) | ||
if not old: | ||
ret["comment"] = "Package {0} is not installed".format(name) | ||
ret["result"] = True | ||
return ret | ||
|
||
if __opts__["test"]: | ||
ret["comment"] = "Package {0} would have been removed".format(name) | ||
ret["result"] = None | ||
ret["pchanges"]["old"] = old[0]["version"] | ||
ret["pchanges"]["new"] = None | ||
return ret | ||
|
||
remove = __salt__["snap.remove"](name) | ||
ret["comment"] = "Package {0} removed".format(name) | ||
ret["result"] = True | ||
ret["changes"]["old"] = old[0]["version"] | ||
ret["changes"]["new"] = None | ||
return ret |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been testing out using these modules in the
packages-formula
, to replace the use ofcmd.run
forsnap
installations. Hit a traceback with this line:Looking at the code, realised that this line should actually be:
Left over from a copy-paste of L53 above, perhaps.
@lordcirth As the original PR author, would you mind confirming this suggestion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@myii Sounds correct to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Appreciate the response, @lordcirth. I've got another question, if you don't mind.
I've found that the execution module functions are returning bytes instead of string objects (where relevant). Should
__salt__["cmd.run_all"]()
be used instead ofsubprocess.check_output()
? Checking across other modules, that seems to be the main method being used when working with command output.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not very experienced with Python or Saltstack internals. Your guess is probably better than mine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lordcirth OK, If I get around to pushing this to the
packages-formula
, I'll try to refactor it accordingly. I'll report back here on how things work out. Thanks again for the prompt response -- and for providing these modules in the first place!