Skip to content

Commit

Permalink
Merge pull request #82 from grycap/devel
Browse files Browse the repository at this point in the history
Devel
  • Loading branch information
micafer authored Mar 8, 2022
2 parents b13756b + 088ce5e commit 8528866
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 22 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,15 @@ im_client.py [-u|--xmlrpc-url <url>] [-r|--restapi-url <url>] [-v|--verify-ssl]
It has an optional parameter ``maxTime`` with the max time to wait. It returns 0 if the infrastructure ends
with a "configured" state or 1 otherwise.

``create_wait_outputs inputfile``
``create_wait_outputs <radlfile>``
This operation is a combination of the create, wait and getoutputs functions. First it creates the
infrastructure using the specified ``inputfile``, then waits for it to be configured, and finally
gets the TOSCA outputs. In case of failure in then infrastructure creation step only the error message
will be returned. The results will be returned to stdout in json format::

{"infid": "ID", "error": "Error message"}

``change_auth <infId> <newAuthFile> [overwrite]``
This operation enables to change the owner of infrastructure with ID ``infId`` using the authentication
data from file ``newAuthFile``. The ``overwrite`` parameter is optional and is a flag to specify if the
authentication data will be overwrited or will be appended. The default value is 0.
99 changes: 78 additions & 21 deletions im_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,14 @@ def __init__(self, options, auth_data, args):
self.options = options
self.auth_data = auth_data
if options.restapi and auth_data:
for item in auth_data:
for key, value in item.items():
value = value.replace("\n", "\\\\n")
self.rest_auth_data += "%s = %s;" % (key, value)
self.rest_auth_data += "\\n"
if isinstance(auth_data, str):
self.rest_auth_data = auth_data
else:
for item in auth_data:
for key, value in item.items():
value = value.replace("\n", "\\\\n")
self.rest_auth_data += "%s = %s;" % (key, value)
self.rest_auth_data += "\\n"

elif options.xmlrpc:
if options.xmlrpc.startswith("https") and not options.verify:
Expand All @@ -264,6 +267,22 @@ def __init__(self, options, auth_data, args):
pass
self.server = ServerProxy(options.xmlrpc, allow_none=True)

@staticmethod
def replace_auth_values(value):
# Enable to specify a commnad and set the contents of the output
if value.startswith("command(") and value.endswith(")"):
command = value[8:-1]
return IMClient._run_command(command)
# Enable to specify a filename and set the contents of it
elif value.startswith("file(") and value.endswith(")"):
try:
with open(value[5:-1], 'r') as f:
data = f.read()
return data.strip()
except Exception:
pass
return value

# From IM.auth
@staticmethod
def read_auth_data(filename):
Expand All @@ -276,6 +295,10 @@ def read_auth_data(filename):

res = []

if len(lines) == 1 and lines[0].startswith("Bearer "):
token = lines[0].strip()[7:]
return "Bearer %s" % IMClient.replace_auth_values(token)

for line in lines:
line = line.strip()
if len(line) > 0 and not line.startswith("#"):
Expand All @@ -288,21 +311,7 @@ def read_auth_data(filename):
else:
key = key_value[0].strip()
value = key_value[1].strip().replace("\\n", "\n")
# Enable to specify a commnad and set the contents of the output
if value.startswith("command(") and value.endswith(")"):
command = value[8:len(value) - 1]
value = IMClient._run_command(command)
# Enable to specify a filename and set the contents of it
elif value.startswith("file(") and value.endswith(")"):
filename = value[5:len(value) - 1]
try:
value_file = open(filename, 'r')
value = value_file.read()
value_file.close()
except Exception:
pass

auth[key] = value
auth[key] = IMClient.replace_auth_values(value)
res.append(auth)

return res
Expand Down Expand Up @@ -885,6 +894,44 @@ def wait(self):
else:
return False, "The infrastructure is in state: %s" % state

def change_auth(self):
inf_id = self.get_inf_id()
if len(self.args) >= 2:
if not os.path.isfile(self.args[1]):
return False, "New auth file '" + self.args[1] + "' does not exist"
else:
return False, "JSON file to create inf. not specified"

new_auth_data = []
for elem in IMClient.read_auth_data(self.args[1]):
if "type" in elem and elem["type"] == "InfrastructureManager":
new_auth_data.append(elem)
break

if not new_auth_data:
return False, "No new InfrastructureManager auth provided."

overwrite = False
if len(self.args) >= 3:
if self.args[2] in ["0", "1"]:
overwrite = bool(int(self.args[2]))
else:
return False, "The overwrite flag must be 0 or 1"

if self.options.restapi:
headers = {"Authorization": self.rest_auth_data}
url = "%s/infrastructures/%s/authorization" % (self.options.restapi, inf_id)
if overwrite:
url += "?overwrite=1"
resp = requests.request("POST", url, verify=self.options.verify,
headers=headers, data=json.dumps(new_auth_data[0]))
success = resp.status_code == 200
info = resp.text
else:
(success, info) = self.server.ChangeInfrastructureAuth(inf_id, new_auth_data[0], overwrite, self.auth_data)

return success, info


def main(operation, options, args, parser):
"""
Expand All @@ -898,7 +945,7 @@ def main(operation, options, args, parser):
if (operation not in ["removeresource", "addresource", "create", "destroy", "getinfo", "list", "stop", "start",
"alter", "getcontmsg", "getvminfo", "reconfigure", "getradl", "getvmcontmsg", "stopvm",
"startvm", "sshvm", "ssh", "getstate", "getversion", "export", "import", "getoutputs",
"rebootvm", "cloudusage", "cloudimages", "wait", "create_wait_outputs"]):
"rebootvm", "cloudusage", "cloudimages", "wait", "create_wait_outputs", "change_auth"]):
parser.error("operation not recognised. Use --help to show all the available operations")

auth_data = None
Expand Down Expand Up @@ -1202,6 +1249,15 @@ def main(operation, options, args, parser):
print('{"infid": "%s", "error": "%s"}' % (inf_id, outputs))
return False

elif operation == "change_auth":
success, error = imclient.change_auth()
if success:
if not options.quiet:
print("Auth data successfully changed.")
else:
print("ERROR changing auth data: " + error)
return success


def get_parser():
"""
Expand Down Expand Up @@ -1273,6 +1329,7 @@ def get_parser():
parser.add_operation_help('getversion', '')
parser.add_operation_help('wait', '<inf_id> <max_time>')
parser.add_operation_help('create_wait_outputs', '<radl_file>')
parser.add_operation_help('change_auth', '<inf_id> <new_auth_file>')

return parser

Expand Down
1 change: 1 addition & 0 deletions test/files/auth_new.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
type = InfrastructureManager; username = user1; password = pass1
18 changes: 18 additions & 0 deletions test/unit/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ def get_response(method, url, verify, cert=None, headers=None, data=None):
resp.status_code = 200
resp.text = ('{ "uri-list": [ { "uri" : "http://localhost/infid/vms/1" }]}')
resp.json.return_value = json.loads(resp.text)
elif url == "/infrastructures/infid/authorization":
resp.status_code = 200
resp.text = ""
else:
resp.status_code = 404
elif method == "DELETE":
Expand Down Expand Up @@ -1191,6 +1194,21 @@ def test_create_wait_outputs(self, requests):
self.assertEqual(output, {"infid": "inf1", "output1": "value1" , "output2": "value2"})
sys.stdout = oldstdout

@patch('requests.request')
def test_change_user(self, requests):
"""
Test create_wait_outputs operation
"""
requests.side_effect = self.get_response
options = MagicMock()
options.auth_file = get_abs_path("../../auth.dat")
options.restapi = "https://localhost:8800"
options.xmlrpc = None
options.quiet = True
parser = MagicMock()

res = main("change_auth", options, ["infid", get_abs_path("../files/auth_new.dat")], parser)
self.assertEquals(res, True)


if __name__ == '__main__':
Expand Down

0 comments on commit 8528866

Please sign in to comment.