Skip to content

Commit

Permalink
make salt-api arg/kwarg handling the same as cli
Browse files Browse the repository at this point in the history
both cherrypy and saltnado now pass all args through parse_input to
allow for behavior equivalent to salt cli yaml based arg parsing. This
will allow for pepper to behave more like salt cli, or direct api users.
  • Loading branch information
mattp- committed Oct 19, 2018
1 parent 34db527 commit a2e09d7
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 9 deletions.
11 changes: 9 additions & 2 deletions salt/netapi/rest_cherrypy/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@
import salt
import salt.auth
import salt.exceptions
import salt.utils.args
import salt.utils.event
import salt.utils.json
import salt.utils.stringutils
Expand Down Expand Up @@ -1172,8 +1173,14 @@ def exec_lowstate(self, client=None, token=None):

# Make any 'arg' params a list if not already.
# This is largely to fix a deficiency in the urlencoded format.
if 'arg' in chunk and not isinstance(chunk['arg'], list):
chunk['arg'] = [chunk['arg']]
if 'arg' in chunk:
if not isinstance(chunk['arg'], list):
chunk['arg'] = [chunk['arg']]

# Run name=value args through parse_input
_arg, _kwarg = salt.utils.args.parse_input(chunk.pop('arg', []), condition=False)
chunk['arg'] = _arg
chunk.update(_kwarg)

ret = self.api.run(chunk)

Expand Down
14 changes: 12 additions & 2 deletions salt/netapi/rest_tornado/saltnado.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,11 +559,21 @@ def _get_lowstate(self):
'''
if not self.request.body:
return

data = self.deserialize(self.request.body)
self.request_payload = copy(data)

if data and 'arg' in data and not isinstance(data['arg'], list):
data['arg'] = [data['arg']]
if data and 'arg' in data:
if not isinstance(data['arg'], list):
data['arg'] = [data['arg']]

# Run name=value args through parse_input
_arg, _kwarg = salt.utils.args.parse_input(data.pop('arg', []), condition=False)
data['arg'] = _arg
if 'kwarg' in data and isinstance(data['kwarg'], dict):
data['kwarg'].update(_kwarg)
else:
data['kwarg'] = _kwarg

if not isinstance(data, list):
lowstate = [data]
Expand Down
7 changes: 3 additions & 4 deletions tests/integration/netapi/rest_cherrypy/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class TestArgKwarg(cptc.BaseRestCherryPyTest):
('client', 'runner'),
('fun', 'test.arg'),
# use singular form for arg and kwarg
('arg', [1234]),
('arg', [1234, '56', 'yaml={baz: bar}']),
('kwarg', {'ext_source': 'redis'}),
)

Expand Down Expand Up @@ -197,9 +197,8 @@ def test_accepts_arg_kwarg_keys(self):
}
)
resp = salt.utils.json.loads(salt.utils.stringutils.to_str(response.body[0]))
self.assertEqual(resp['return'][0]['args'], [1234])
self.assertEqual(resp['return'][0]['kwargs'],
{'ext_source': 'redis'})
self.assertEqual(resp['return'][0]['args'], [1234, 56])
self.assertEqual(resp['return'][0]['kwargs'], {'ext_source': 'redis', 'yaml': {'baz': 'bar'}})


class TestJobs(cptc.BaseRestCherryPyTest):
Expand Down
25 changes: 24 additions & 1 deletion tests/integration/netapi/rest_tornado/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def get_app(self):

application.event_listener = saltnado.EventListener({}, self.opts)
self.application = application

return application

def test_root(self):
Expand Down Expand Up @@ -121,8 +122,30 @@ def test_simple_local_post_no_tgt(self):
response_obj = salt.utils.json.loads(response.body)
self.assertEqual(response_obj['return'], ["No minions matched the target. No command was sent, no jid was assigned."])

# local client request body test
# arg/kwarg parsing test
def test_simple_arg_kwarg_parsing(self):
'''
POST job to test arg/kwarg parsing
'''
low = {'client': 'local',
'tgt': 'minion',
'fun': 'test.arg_clean',
'arg': [1, '2', 'yaml={bar: baz}'],
'kwarg': {'a': 'b'}
}
response = self.fetch('/',
method='POST',
body=salt.utils.json.dumps(low),
headers={'Content-Type': self.content_type_map['json'],
saltnado.AUTH_TOKEN_HEADER: self.token['token']},
connect_timeout=30,
request_timeout=30,
)
response_obj = salt.utils.json.loads(response.body)
self.assertEqual(response_obj['return'][0]['minion']['args'], [1, 2])
self.assertEqual(response_obj['return'][0]['minion']['kwargs'], {'a': 'b', 'yaml': {'bar': 'baz'}})

# local client request body test
@skipIf(True, 'Undetermined race condition in test. Temporarily disabled.')
def test_simple_local_post_only_dictionary_request(self):
'''
Expand Down

0 comments on commit a2e09d7

Please sign in to comment.