{"action":"created","comment":{"url":"https://api.github.com/repos/StackStorm/st2/pulls/comments/47429175","id":47429175,"diff_hunk":"@@ -45,295 +43,158 @@ def pf(params, skips):\n     return (pf(runner_parameters, {}), pf(action_parameters, runner_parameters))\n \n \n-def _get_resolved_runner_params(runner_parameters, action_parameters,\n-                                actionexec_runner_parameters):\n-    # Runner parameters should use the defaults from the RunnerType object.\n-    # The runner parameter defaults may be overridden by values provided in\n-    # the Action and liveaction.\n+def _cast_params(rendered, parameter_schemas):\n+    '''\n+    It's just here to make tests happy\n+    '''\n+    casted_params = {}\n+    for k, v in six.iteritems(rendered):\n+        casted_params[k] = _cast(v, parameter_schemas[k] or {})\n+    return casted_params\n \n-    # Create runner parameter by merging default values with dynamic values\n-    resolved_params = {k: v['default'] if 'default' in v else None\n-                       for k, v in six.iteritems(runner_parameters)}\n \n-    # pick overrides from action_parameters & actionexec_runner_parameters\n-    for param_name, param_value in six.iteritems(runner_parameters):\n-        # No override if param is immutable\n-        if param_value.get('immutable', False):\n-            continue\n+def _cast(v, parameter_schema):\n+    if v is None or not parameter_schema:\n+        return v\n \n-        # Check if param exists in action_parameters and if it has a default value then\n-        # pickup the override.\n-        if param_name in action_parameters:\n-            action_param = action_parameters[param_name]\n-            if 'default' in action_param:\n-                resolved_params[param_name] = action_param['default']\n+    parameter_type = parameter_schema.get('type', None)\n+    if not parameter_type:\n+        return v\n \n-            # No further override (from liveaction) if param is immutable\n-            if action_param.get('immutable', False):\n-                continue\n+    cast = get_cast(cast_type=parameter_type)\n+    if not cast:\n+        return v\n \n-        # Finally pick up override from actionexec_runner_parameters\n-        if param_name in actionexec_runner_parameters:\n-            resolved_params[param_name] = actionexec_runner_parameters[param_name]\n+    return cast(v)\n \n-    return resolved_params\n \n+def process(G, name, value):\n+    env = Environment(undefined=StrictUndefined)\n+    if isinstance(value, str):","path":"st2actions/st2actions/utils/param_utils.py","position":80,"original_position":80,"commit_id":"02e17a81157984521137649e1a2749d8e30991a8","original_commit_id":"02e17a81157984521137649e1a2749d8e30991a8","user":{"login":"manasdk","id":1776099,"avatar_url":"https://avatars.githubusercontent.com/u/1776099?v=3","gravatar_id":"","url":"https://api.github.com/users/manasdk","html_url":"https://github.com/manasdk","followers_url":"https://api.github.com/users/manasdk/followers","following_url":"https://api.github.com/users/manasdk/following{/other_user}","gists_url":"https://api.github.com/users/manasdk/gists{/gist_id}","starred_url":"https://api.github.com/users/manasdk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manasdk/subscriptions","organizations_url":"https://api.github.com/users/manasdk/orgs","repos_url":"https://api.github.com/users/manasdk/repos","events_url":"https://api.github.com/users/manasdk/events{/privacy}","received_events_url":"https://api.github.com/users/manasdk/received_events","type":"User","site_admin":false},"body":"Actually I wanted you to drop a comment in the code.","created_at":"2015-12-12T08:17:13Z","updated_at":"2015-12-12T08:17:13Z","html_url":"https://github.com/StackStorm/st2/pull/2288#discussion_r47429175","pull_request_url":"https://api.github.com/repos/StackStorm/st2/pulls/2288","_links":{"self":{"href":"https://api.github.com/repos/StackStorm/st2/pulls/comments/47429175"},"html":{"href":"https://github.com/StackStorm/st2/pull/2288#discussion_r47429175"},"pull_request":{"href":"https://api.github.com/repos/StackStorm/st2/pulls/2288"}}},"pull_request":{"url":"https://api.github.com/repos/StackStorm/st2/pulls/2288","id":53387442,"html_url":"https://github.com/StackStorm/st2/pull/2288","diff_url":"https://github.com/StackStorm/st2/pull/2288.diff","patch_url":"https://github.com/StackStorm/st2/pull/2288.patch","issue_url":"https://api.github.com/repos/StackStorm/st2/issues/2288","number":2288,"state":"open","locked":false,"title":"Fix double rendering issue","user":{"login":"enykeev","id":1357357,"avatar_url":"https://avatars.githubusercontent.com/u/1357357?v=3","gravatar_id":"","url":"https://api.github.com/users/enykeev","html_url":"https://github.com/enykeev","followers_url":"https://api.github.com/users/enykeev/followers","following_url":"https://api.github.com/users/enykeev/following{/other_user}","gists_url":"https://api.github.com/users/enykeev/gists{/gist_id}","starred_url":"https://api.github.com/users/enykeev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/enykeev/subscriptions","organizations_url":"https://api.github.com/users/enykeev/orgs","repos_url":"https://api.github.com/users/enykeev/repos","events_url":"https://api.github.com/users/enykeev/events{/privacy}","received_events_url":"https://api.github.com/users/enykeev/received_events","type":"User","site_admin":false},"body":"The problem we're currently having is that in some cases, st2 attempts to render templates for a single action twice: first time it does that in context of actionchain\\rule engine and the second time happens in context of action container. So if the first render resulting in parameter having a new template (either by string concatenation or by results of previous action containing a template as a string inside of it), it tries and usually fails to evaluate this new template during the second attempt.\r\n\r\nThe solution for this problem is to make sure every string only rendered once. One of the ways to achieve that is to make sure we only rendering user input ad not already processed data.\r\n\r\nCurrently, there's 5 places in st2 where jinja rendering is happening and 5 artifacts that are getting rendered there: action chain runner transform templates from action chain workflow definitions, reactor transform templates from rule definitions, notifier transforms notifications from action definitions, chatops pack transforms formats from aliases and action container handles user input on manual action invocation, mistral calls (which are at the moment basically the same thing) and, due to some previous oversight, the results of the previous four transformations.\r\n\r\nIn case problem is not obvious to you, here is an example of an action chain that throws an error which from the looks of it, it should not:\r\n\r\n```yaml\r\n---\r\nchain:\r\n    -\r\n        name: \"do\"\r\n        ref: \"core.local\"\r\n        params:\r\n            cmd: \"echo -n {; echo -n { missing_variable }}\"\r\n        on-success: \"fail\"\r\n    -\r\n        name: \"fail\"\r\n        ref: \"core.local\"\r\n        params:\r\n            cmd: \"echo {{ do.stdout }}\"\r\n```\r\n\r\nAfter the first action has been executed, it's stdout now contains a string `{{ missing_variable }}` which should be treated by the system as any other source of random data, simply as a string. Action chain transformer resolves `{{ do.stdout }}` in `cmd` parameter during an execution of a second task and sends the resulting `echo {{ missing_variable }}` to action container which also treats it as a template instead of a simple string and returns `missing dependency` error because clearly, there's no such variable in action context. Or in case the variable is here, it passes correctly and then does something very different from what author initially planned.\r\n\r\nSo, to make sure every template only rendered once I'm proposing to split action container renderer into two independent functions and wire the system in such a way, that calls coming from mistral or user input are handled with both functions when the one coming from action chain or reactor only processed by the second one. First function should only transform parameters user have entered during this particular execution (aka liveaction.parameters). Second one would be handling parameters that user haven't provided, but are still required for action to execute (defaults from runner and action parameters). We should treat parameters coming from rule engine and action chain as already transformed and only use them as values for rendering default ones.\r\n\r\nSince this change would require us to almost completely rewrite action container renderer, I've also decided to implement a new one using `networkx` graph library to determine the dependency graph instead of iterating over parameters until they are all rendered or failed enough times.\r\n","created_at":"2015-12-11T12:34:28Z","updated_at":"2015-12-12T08:17:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0dfedacd5650ecc15ed71f31665cc02191109a5c","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/StackStorm/st2/pulls/2288/commits","review_comments_url":"https://api.github.com/repos/StackStorm/st2/pulls/2288/comments","review_comment_url":"https://api.github.com/repos/StackStorm/st2/pulls/comments{/number}","comments_url":"https://api.github.com/repos/StackStorm/st2/issues/2288/comments","statuses_url":"https://api.github.com/repos/StackStorm/st2/statuses/02e17a81157984521137649e1a2749d8e30991a8","head":{"label":"StackStorm:fix/double_rendering","ref":"fix/double_rendering","sha":"02e17a81157984521137649e1a2749d8e30991a8","user":{"login":"StackStorm","id":4969009,"avatar_url":"https://avatars.githubusercontent.com/u/4969009?v=3","gravatar_id":"","url":"https://api.github.com/users/StackStorm","html_url":"https://github.com/StackStorm","followers_url":"https://api.github.com/users/StackStorm/followers","following_url":"https://api.github.com/users/StackStorm/following{/other_user}","gists_url":"https://api.github.com/users/StackStorm/gists{/gist_id}","starred_url":"https://api.github.com/users/StackStorm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/StackStorm/subscriptions","organizations_url":"https://api.github.com/users/StackStorm/orgs","repos_url":"https://api.github.com/users/StackStorm/repos","events_url":"https://api.github.com/users/StackStorm/events{/privacy}","received_events_url":"https://api.github.com/users/StackStorm/received_events","type":"Organization","site_admin":false},"repo":{"id":19051806,"name":"st2","full_name":"StackStorm/st2","owner":{"login":"StackStorm","id":4969009,"avatar_url":"https://avatars.githubusercontent.com/u/4969009?v=3","gravatar_id":"","url":"https://api.github.com/users/StackStorm","html_url":"https://github.com/StackStorm","followers_url":"https://api.github.com/users/StackStorm/followers","following_url":"https://api.github.com/users/StackStorm/following{/other_user}","gists_url":"https://api.github.com/users/StackStorm/gists{/gist_id}","starred_url":"https://api.github.com/users/StackStorm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/StackStorm/subscriptions","organizations_url":"https://api.github.com/users/StackStorm/orgs","repos_url":"https://api.github.com/users/StackStorm/repos","events_url":"https://api.github.com/users/StackStorm/events{/privacy}","received_events_url":"https://api.github.com/users/StackStorm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/StackStorm/st2","description":"StackStorm (aka \"IFTTT for Ops\") is event-driven automation commonly used for auto-remediation, security responses, facilitated troubleshooting, complex deployments, and more. Includes rules engine, workflow,1800+ integrations (see /st2contrib), native ChatOps and so forth.  Installer available at http://docs.stackstorm.com/install/index.html. Ping us on slack - https://stackstorm-community.slack.com/. ","fork":false,"url":"https://api.github.com/repos/StackStorm/st2","forks_url":"https://api.github.com/repos/StackStorm/st2/forks","keys_url":"https://api.github.com/repos/StackStorm/st2/keys{/key_id}","collaborators_url":"https://api.github.com/repos/StackStorm/st2/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/StackStorm/st2/teams","hooks_url":"https://api.github.com/repos/StackStorm/st2/hooks","issue_events_url":"https://api.github.com/repos/StackStorm/st2/issues/events{/number}","events_url":"https://api.github.com/repos/StackStorm/st2/events","assignees_url":"https://api.github.com/repos/StackStorm/st2/assignees{/user}","branches_url":"https://api.github.com/repos/StackStorm/st2/branches{/branch}","tags_url":"https://api.github.com/repos/StackStorm/st2/tags","blobs_url":"https://api.github.com/repos/StackStorm/st2/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/StackStorm/st2/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/StackStorm/st2/git/refs{/sha}","trees_url":"https://api.github.com/repos/StackStorm/st2/git/trees{/sha}","statuses_url":"https://api.github.com/repos/StackStorm/st2/statuses/{sha}","languages_url":"https://api.github.com/repos/StackStorm/st2/languages","stargazers_url":"https://api.github.com/repos/StackStorm/st2/stargazers","contributors_url":"https://api.github.com/repos/StackStorm/st2/contributors","subscribers_url":"https://api.github.com/repos/StackStorm/st2/subscribers","subscription_url":"https://api.github.com/repos/StackStorm/st2/subscription","commits_url":"https://api.github.com/repos/StackStorm/st2/commits{/sha}","git_commits_url":"https://api.github.com/repos/StackStorm/st2/git/commits{/sha}","comments_url":"https://api.github.com/repos/StackStorm/st2/comments{/number}","issue_comment_url":"https://api.github.com/repos/StackStorm/st2/issues/comments{/number}","contents_url":"https://api.github.com/repos/StackStorm/st2/contents/{+path}","compare_url":"https://api.github.com/repos/StackStorm/st2/compare/{base}...{head}","merges_url":"https://api.github.com/repos/StackStorm/st2/merges","archive_url":"https://api.github.com/repos/StackStorm/st2/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/StackStorm/st2/downloads","issues_url":"https://api.github.com/repos/StackStorm/st2/issues{/number}","pulls_url":"https://api.github.com/repos/StackStorm/st2/pulls{/number}","milestones_url":"https://api.github.com/repos/StackStorm/st2/milestones{/number}","notifications_url":"https://api.github.com/repos/StackStorm/st2/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/StackStorm/st2/labels{/name}","releases_url":"https://api.github.com/repos/StackStorm/st2/releases{/id}","created_at":"2014-04-23T00:51:34Z","updated_at":"2015-12-11T23:19:36Z","pushed_at":"2015-12-12T00:41:34Z","git_url":"git://github.com/StackStorm/st2.git","ssh_url":"git@github.com:StackStorm/st2.git","clone_url":"https://github.com/StackStorm/st2.git","svn_url":"https://github.com/StackStorm/st2","homepage":"http://www.stackstorm.com/","size":15023,"stargazers_count":1093,"watchers_count":1093,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":93,"mirror_url":null,"open_issues_count":89,"forks":93,"open_issues":89,"watchers":1093,"default_branch":"master"}},"base":{"label":"StackStorm:master","ref":"master","sha":"d5e0ce45ab7b6a0ab94071bd58fc5c531de27cb7","user":{"login":"StackStorm","id":4969009,"avatar_url":"https://avatars.githubusercontent.com/u/4969009?v=3","gravatar_id":"","url":"https://api.github.com/users/StackStorm","html_url":"https://github.com/StackStorm","followers_url":"https://api.github.com/users/StackStorm/followers","following_url":"https://api.github.com/users/StackStorm/following{/other_user}","gists_url":"https://api.github.com/users/StackStorm/gists{/gist_id}","starred_url":"https://api.github.com/users/StackStorm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/StackStorm/subscriptions","organizations_url":"https://api.github.com/users/StackStorm/orgs","repos_url":"https://api.github.com/users/StackStorm/repos","events_url":"https://api.github.com/users/StackStorm/events{/privacy}","received_events_url":"https://api.github.com/users/StackStorm/received_events","type":"Organization","site_admin":false},"repo":{"id":19051806,"name":"st2","full_name":"StackStorm/st2","owner":{"login":"StackStorm","id":4969009,"avatar_url":"https://avatars.githubusercontent.com/u/4969009?v=3","gravatar_id":"","url":"https://api.github.com/users/StackStorm","html_url":"https://github.com/StackStorm","followers_url":"https://api.github.com/users/StackStorm/followers","following_url":"https://api.github.com/users/StackStorm/following{/other_user}","gists_url":"https://api.github.com/users/StackStorm/gists{/gist_id}","starred_url":"https://api.github.com/users/StackStorm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/StackStorm/subscriptions","organizations_url":"https://api.github.com/users/StackStorm/orgs","repos_url":"https://api.github.com/users/StackStorm/repos","events_url":"https://api.github.com/users/StackStorm/events{/privacy}","received_events_url":"https://api.github.com/users/StackStorm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/StackStorm/st2","description":"StackStorm (aka \"IFTTT for Ops\") is event-driven automation commonly used for auto-remediation, security responses, facilitated troubleshooting, complex deployments, and more. Includes rules engine, workflow,1800+ integrations (see /st2contrib), native ChatOps and so forth.  Installer available at http://docs.stackstorm.com/install/index.html. Ping us on slack - https://stackstorm-community.slack.com/. ","fork":false,"url":"https://api.github.com/repos/StackStorm/st2","forks_url":"https://api.github.com/repos/StackStorm/st2/forks","keys_url":"https://api.github.com/repos/StackStorm/st2/keys{/key_id}","collaborators_url":"https://api.github.com/repos/StackStorm/st2/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/StackStorm/st2/teams","hooks_url":"https://api.github.com/repos/StackStorm/st2/hooks","issue_events_url":"https://api.github.com/repos/StackStorm/st2/issues/events{/number}","events_url":"https://api.github.com/repos/StackStorm/st2/events","assignees_url":"https://api.github.com/repos/StackStorm/st2/assignees{/user}","branches_url":"https://api.github.com/repos/StackStorm/st2/branches{/branch}","tags_url":"https://api.github.com/repos/StackStorm/st2/tags","blobs_url":"https://api.github.com/repos/StackStorm/st2/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/StackStorm/st2/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/StackStorm/st2/git/refs{/sha}","trees_url":"https://api.github.com/repos/StackStorm/st2/git/trees{/sha}","statuses_url":"https://api.github.com/repos/StackStorm/st2/statuses/{sha}","languages_url":"https://api.github.com/repos/StackStorm/st2/languages","stargazers_url":"https://api.github.com/repos/StackStorm/st2/stargazers","contributors_url":"https://api.github.com/repos/StackStorm/st2/contributors","subscribers_url":"https://api.github.com/repos/StackStorm/st2/subscribers","subscription_url":"https://api.github.com/repos/StackStorm/st2/subscription","commits_url":"https://api.github.com/repos/StackStorm/st2/commits{/sha}","git_commits_url":"https://api.github.com/repos/StackStorm/st2/git/commits{/sha}","comments_url":"https://api.github.com/repos/StackStorm/st2/comments{/number}","issue_comment_url":"https://api.github.com/repos/StackStorm/st2/issues/comments{/number}","contents_url":"https://api.github.com/repos/StackStorm/st2/contents/{+path}","compare_url":"https://api.github.com/repos/StackStorm/st2/compare/{base}...{head}","merges_url":"https://api.github.com/repos/StackStorm/st2/merges","archive_url":"https://api.github.com/repos/StackStorm/st2/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/StackStorm/st2/downloads","issues_url":"https://api.github.com/repos/StackStorm/st2/issues{/number}","pulls_url":"https://api.github.com/repos/StackStorm/st2/pulls{/number}","milestones_url":"https://api.github.com/repos/StackStorm/st2/milestones{/number}","notifications_url":"https://api.github.com/repos/StackStorm/st2/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/StackStorm/st2/labels{/name}","releases_url":"https://api.github.com/repos/StackStorm/st2/releases{/id}","created_at":"2014-04-23T00:51:34Z","updated_at":"2015-12-11T23:19:36Z","pushed_at":"2015-12-12T00:41:34Z","git_url":"git://github.com/StackStorm/st2.git","ssh_url":"git@github.com:StackStorm/st2.git","clone_url":"https://github.com/StackStorm/st2.git","svn_url":"https://github.com/StackStorm/st2","homepage":"http://www.stackstorm.com/","size":15023,"stargazers_count":1093,"watchers_count":1093,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":93,"mirror_url":null,"open_issues_count":89,"forks":93,"open_issues":89,"watchers":1093,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/StackStorm/st2/pulls/2288"},"html":{"href":"https://github.com/StackStorm/st2/pull/2288"},"issue":{"href":"https://api.github.com/repos/StackStorm/st2/issues/2288"},"comments":{"href":"https://api.github.com/repos/StackStorm/st2/issues/2288/comments"},"review_comments":{"href":"https://api.github.com/repos/StackStorm/st2/pulls/2288/comments"},"review_comment":{"href":"https://api.github.com/repos/StackStorm/st2/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/StackStorm/st2/pulls/2288/commits"},"statuses":{"href":"https://api.github.com/repos/StackStorm/st2/statuses/02e17a81157984521137649e1a2749d8e30991a8"}}}}