I have a bundle of Python actions in vRO and would like for a few of them to reference other (mostly also Python) vRO actions from different vRO modules.
What would be the best way to do this? At the moment the only way I can think of to accomplish this task, is to execute a REST query to launch the action, there does not seem a more "native" way to do it, like with System.getModule....
I'm downloading Python code into the container from other action scripts using the API and then adding them to the Python path so I can import them on the fly. Here's the bootstrap code.
onboardingUtils is just a plain Python module, i.e. no module.handler and not even called directly in vRO. vacfg_constants is a set of constants in another Python module that is imported by onboardingUtils. I.e. onboardingUtils depends on vacfg_constants. As long as you have the other Python action bits inside the container, you should be able to load them into your main action.
onboardingUtils = None
_vcoUrl_ = None
_vcoToken_ = None
_headers_ = None
def handler(context, inputs):
global onboardingUtils
global _vcoUrl_
global _vcoToken_
global _headers_
_vcoUrl_ = context['vcoUrl']
_vcoToken_ = context['getToken']()
_headers_ = {
'accept': 'application/json',
'authorization': "Bearer " + _vcoToken_
}
os.chdir(inputs['workdir'])
sys.path.append(inputs['workdir'])
downloadAction('com.client.vmware.vra.onboarding','onboardingUtils', 'onboardingUtils.py')
downloadAction('com.client.vmware.vra.onboarding', 'vacfg_constants', 'vacfg_constants.py')
import onboardingUtils
onboardingUtils = sys.modules['onboardingUtils']
def downloadAction(module, action, file_path):
url = f'{_vcoUrl_}/api/actions/{module}/{action}'
response = requests.get(url, headers=_headers_)
print(response.status_code)
response.raise_for_status()
r = json.loads(response.text)
open(file_path, 'w').write(r['script'])
If it is a workflow, I'd simply add actions as steps to it.
In an action, you can create python modules within the zip bundle, and import them in your script.
But this would not work for a custom python environment. If I have to use some popular modules like requests, I would have to bundle my own modules and those I would normally add as a dependency in a custom env, which mean I'd have to update them all manually somewhere in the future.
This is an approach I was looking for though - create you own modules from python functions, and upload them into the custom environment, so every action that runs in that env can use it.
I think I will settle for a "wrapper" function written in js for now, that would load all configuration elements and resource elements in the first step, and pass the values on to python actions, which would be referenced by the traditional System.getModule("my.py.actions") method.
I'm downloading Python code into the container from other action scripts using the API and then adding them to the Python path so I can import them on the fly. Here's the bootstrap code.
onboardingUtils is just a plain Python module, i.e. no module.handler and not even called directly in vRO. vacfg_constants is a set of constants in another Python module that is imported by onboardingUtils. I.e. onboardingUtils depends on vacfg_constants. As long as you have the other Python action bits inside the container, you should be able to load them into your main action.
onboardingUtils = None
_vcoUrl_ = None
_vcoToken_ = None
_headers_ = None
def handler(context, inputs):
global onboardingUtils
global _vcoUrl_
global _vcoToken_
global _headers_
_vcoUrl_ = context['vcoUrl']
_vcoToken_ = context['getToken']()
_headers_ = {
'accept': 'application/json',
'authorization': "Bearer " + _vcoToken_
}
os.chdir(inputs['workdir'])
sys.path.append(inputs['workdir'])
downloadAction('com.client.vmware.vra.onboarding','onboardingUtils', 'onboardingUtils.py')
downloadAction('com.client.vmware.vra.onboarding', 'vacfg_constants', 'vacfg_constants.py')
import onboardingUtils
onboardingUtils = sys.modules['onboardingUtils']
def downloadAction(module, action, file_path):
url = f'{_vcoUrl_}/api/actions/{module}/{action}'
response = requests.get(url, headers=_headers_)
print(response.status_code)
response.raise_for_status()
r = json.loads(response.text)
open(file_path, 'w').write(r['script'])
Thank you for answering! This is a really interesting solution, I will definitely try this out soon.
What are the 'workdir' inputs used for? Are those paths to python within the container?
The input workdir is the directory inside the container where the action is doing all of its work that needs file system write access. I think by default, the container logs into the /root or / (forget) directory, which is read-only. I think my input is just /tmp directory. I didn't feel like using absolute paths in all my functions, so I do all the work in /tmp.
Thanks!
I hope a similar solution will be developed for configuring a python environment in vRO, so you'll be able to load custom modules from a folder or maybe gitlab directly into the environment, so that a workaround with the additional actions and functions is not needed.