Skip to content

Commit

Permalink
Merge pull request #29 from nzlosh/report_errors
Browse files Browse the repository at this point in the history
Improve error reporting
  • Loading branch information
nzlosh authored Apr 7, 2024
2 parents cf603f8 + 1197c99 commit f053dce
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 59 deletions.
14 changes: 13 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Change Log

## Unreleased; 3.0.0
## Unreleased; 3.0.2

### Add
### Change
### Removed

## 3.0.1

### Add
- Added TLS connection verification.
Expand All @@ -9,10 +15,16 @@
### Change
- Formatted Python code with black.
- Updated client authentication to work with Salt 3004 to 3006 (maybe higher)
- Improved error reporting when HTTP errors are encountered.
- Fail actions when HTTP return codes >=400

### Removed
- Removed salt-pepper as a python dependency.

## 3.0.0

Retracted.

## 2.0.1

* Drop Python 2.7 support
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ One can also use the generic "runner" action to execute arbitrary runners and ex
st2 run salt.local module=pillar.items args=thing1,thing2
```

Wheel command allows manipulation of keys on the master and requires careful crafting of the runner call.
```bash
st2 run salt.runner module=wheel kwargs='{"client": "wheel", "fun": "key.finger", "match": "*"}'
```

### Actions

Saltstack runner/execution module function calls are represented as StackStorm actions. Considering Saltstack's [`archive` execution module](http://docs.saltstack.com/en/2014.7/ref/modules/all/salt.modules.archive.html#module-salt.modules.archive), every function would be exposed as an StackStorm action.
Expand Down
4 changes: 1 addition & 3 deletions actions/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@

class SaltClientAction(Action):
def run(self, matches, module, args=[], kwargs={}):
"""
CLI Examples:
"""CLI Examples:
st2 run salt.client matches='web*' module=test.ping
st2 run salt.client module=pkg.install \
kwargs='{"pkgs":["git","httpd"]}'
Expand Down
22 changes: 12 additions & 10 deletions actions/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ class SaltLocal(SaltAction):
]

def run(self, module, target, tgt_type, args, **kwargs):
"""CLI Examples:
st2 run salt.local module=test.ping matches='web*'
st2 run salt.local module=test.ping tgt_type=grain target='os:Ubuntu'
"""
CLI Examples:
st2 run salt.local module=test.ping matches='web*'
st2 run salt.local module=test.ping tgt_type=grain target='os:Ubuntu'
"""
self.verify_tls = self.config.get("verify_ssl", True)

# ChatOps alias and newer St2 versions set default args=[] which
# breaks test.ping & test.version
Expand All @@ -39,8 +38,11 @@ def run(self, module, target, tgt_type, args, **kwargs):
request = self.generate_request()
request.prepare_body(json.dumps(self.data), None)
resp = Session().send(request, verify=self.verify_tls)
try:
retval = resp.json()
except Exception as exc:
retval = (False, f"Failed to decode json! {str(exc)}")
return retval

if resp.ok:
try:
return resp.json()
except ValueError:
return resp.text
else:
return (False, f"HTTP error {resp.status_code}\n{resp.text}")
23 changes: 14 additions & 9 deletions actions/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,30 @@


class SaltRunner(SaltAction):

__explicit__ = ["jobs", "manage", "pillar", "mine", "network"]

def run(self, module, **kwargs):
"""CLI Examples:
st2 run salt.runner_jobs.active
st2 run salt.runner_jobs.list_jobs
"""
CLI Examples:
self.verify_tls = self.config.get("verify_ssl", True)

st2 run salt.runner_jobs.active
st2 run salt.runner_jobs.list_jobs
"""
_cmd = module

self.generate_package("runner", cmd=_cmd)

if kwargs.get("kwargs", None) is not None:
self.data.update(kwargs["kwargs"])

request = self.generate_request()
self.logger.info("[salt] Request generated")
request.prepare_body(json.dumps(self.data), None)
self.logger.info("[salt] Preparing to send")
resp = Session().send(request, verify=self.verify_tls)
self.logger.debug("[salt] Response http code: %s", resp.status_code)
return resp.json()

if resp.ok:
try:
return resp.json()
except ValueError:
return resp.text
else:
return (False, f"HTTP error {resp.status_code}\n{resp.text}")
5 changes: 2 additions & 3 deletions actions/salt_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

class SaltInstaller(Action):
def run(self, name, provider, instance_id):
client = salt.cloud.CloudClient('/etc/salt/cloud')
ret = client.create(names=[name], provider=provider,
instance_id=instance_id)
client = salt.cloud.CloudClient("/etc/salt/cloud")
ret = client.create(names=[name], provider=provider, instance_id=instance_id)
return ret
2 changes: 1 addition & 1 deletion pack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ keywords:
- salt
- cfg management
- configuration management
version: 3.0.0
version: 3.0.1
author : jcockhren
email : [email protected]
python_versions:
Expand Down
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
salt
salt>=3006,<3007
# dependency of salt 3006
pyzmq==25.0.2
requests
57 changes: 26 additions & 31 deletions tests/test_action_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,26 @@
from requests_mock.contrib import fixture
import testtools

__all__ = [
'SaltLocalActionTestCase'
]
__all__ = ["SaltLocalActionTestCase"]

no_args = {
'module': 'this.something',
'target': '*',
'tgt_type': 'glob',
'args': []
}
no_args = {"module": "this.something", "target": "*", "tgt_type": "glob", "args": []}

one_arg = {
'module': 'this.something',
'target': '*',
'tgt_type': 'glob',
'args': ['os'],
"module": "this.something",
"target": "*",
"tgt_type": "glob",
"args": ["os"],
}

multiple_args = {
'module': 'this.something',
'target': '*',
'tgt_type': 'glob',
'args': ['this', 'that', 'home'],
"module": "this.something",
"target": "*",
"tgt_type": "glob",
"args": ["this", "that", "home"],
}

CONFIG_DATA = {
'api_url': 'https://example.com',
'username': 'this',
'password': 'that'
}
requests_mock.Mocker.TEST_PREFIX = 'test'
CONFIG_DATA = {"api_url": "https://example.com", "username": "this", "password": "that"}
requests_mock.Mocker.TEST_PREFIX = "test"


class SaltLocalActionTestCase(testtools.TestCase, BaseActionTestCase):
Expand All @@ -45,20 +34,26 @@ def setUp(self):
super(SaltLocalActionTestCase, self).setUp()
self.m = self.useFixture(fixture.Fixture())
self.action = self.get_action_instance(config=CONFIG_DATA)
self.m.register_uri('POST',
"{}/run".format(CONFIG_DATA['api_url']),
json={})
# Mock authentication
self.m.register_uri(
"POST",
"{}/login".format(CONFIG_DATA["api_url"]),
json={},
headers={"X-Auth-Token": "mock-auth-ok-token"},
)
# Mock run API
self.m.register_uri("POST", "{}/".format(CONFIG_DATA["api_url"]), json={})

def test_generic_action_no_args(self):
self.action.run(**no_args)
self.assertNotIn('arg', self.action.data)
self.assertNotIn("arg", self.action.data)

def test_generic_action_one_arg(self):
self.action.run(**one_arg)
self.assertIn('arg', self.action.data)
self.assertIsInstance(self.action.data['arg'], list)
self.assertIn("arg", self.action.data)
self.assertIsInstance(self.action.data["arg"], list)

def test_generic_action_multiple_args(self):
self.action.run(**multiple_args)
self.assertIn('arg', self.action.data)
self.assertIsInstance(self.action.data['arg'], list)
self.assertIn("arg", self.action.data)
self.assertIsInstance(self.action.data["arg"], list)

0 comments on commit f053dce

Please sign in to comment.