Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoke-Command: improve handling of variables with $using: expression #16113

Conversation

dwtaber
Copy link
Contributor

@dwtaber dwtaber commented Sep 16, 2021

PR Summary

This PR improves Invoke-Command's handling of cases that combine $using: expressions with variable namespace notation when the -ComputerName parameter is used.
Fixes #9204
Fixes #16019

PR Context

When the -ComputerName parameter is used, Invoke-Command is unable to check which version of PowerShell is available on the remote computer and assumes v2.0. Because PowerShell 2.0 can't parse $using: expressions, the ScriptBlock is modified before sending, with $using: variables renamed to replace the $using: expression with $__using_. Currently, the code that renames these variables doesn't check whether the variable path is qualified. In cases where variable namespace notation is used, this code produces variable names like $__using_env:foo, preventing the remote computer from parsing the variables correctly. The changes in this PR add handling for qualified variable paths, producing variable names like $__using_env_foo

This PR does not fix all issues with the handling of $using: expressions. Variable names that include special characters still aren't parsed correctly, for instance. Since a user technically could name a variable $__using_env_foo, this might be considered an "unlikely grey area" breaking change. Long-term, it might be worth reconsidering how Invoke-Command handles the -ComputerName parameter; always falling back to v2.0 seems unnecessarily restrictive.

PR Checklist

@ghost ghost assigned rjmholt Sep 16, 2021
@ghost
Copy link

ghost commented Sep 16, 2021

CLA assistant check
All CLA requirements met.

@iSazonov
Copy link
Collaborator

When the -ComputerName parameter is used, Invoke-Command is unable to check which version of PowerShell is available on the remote computer and assumes v2.0.

I wonder why we need the workaround if we can prepare full fix.

If I understand correctly, with ComputerName we create new runspace but do not open it in CreateHelpersForSpecifiedComputerNames(), as result we can not detect remote PowerShell version. So I guess we need to open the new runspace in CreateHelpersForSpecifiedComputerNames().

@dwtaber
Copy link
Contributor Author

dwtaber commented Sep 16, 2021

When the -ComputerName parameter is used, Invoke-Command is unable to check which version of PowerShell is available on the remote computer and assumes v2.0.

I wonder why we need the workaround if we can prepare full fix.

If I understand correctly, with ComputerName we create new runspace but do not open it in CreateHelpersForSpecifiedComputerNames(), as result we can not detect remote PowerShell version. So I guess we need to open the new runspace in CreateHelpersForSpecifiedComputerNames().

Implementing proper version detection for the -ComputerName parameter seems preferable to me as well. Since the current behavior (falling back to v2) is documented at various points in the code comments, it seemed to be an intentional design choice, maybe based on factors I wasn't aware of. Honestly, this is the first pull request I've submitted, and I didn't want to overstep with a potentially significant change to how Invoke-Command connections work, so I went with a more conservative fix, but I'm not married to it.

@dwtaber
Copy link
Contributor Author

dwtaber commented Sep 22, 2021

Can I get some guidance on the two tests that have failed? It looks like Invoke-WebRequest failed to reach a URI, but I can't see how my changes would have affected that cmdlet. Is it possible the resource was just unavailable when the test was run?

I'd also appreciate any suggestions on writing a Pester test for this issue. I don't think any of the current remoting tests target a remote computer, so they don't offer much guidance. So far I've been testing against computers available to me, but obviously that's too context-dependent to be of use to anyone else. Are there any designated endpoints for this sort of testing?

@iSazonov
Copy link
Collaborator

I restarted CI-static.

@ghost ghost added the Review - Needed The PR is being reviewed label Sep 30, 2021
@ghost
Copy link

ghost commented Sep 30, 2021

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days.
Maintainer, please provide feedback and/or mark it as Waiting on Author

@@ -1261,7 +1261,8 @@ internal string ToStringForSerialization(Tuple<List<VariableExpressionAst>, stri
var varAst = ast as VariableExpressionAst;
if (varAst != null)
{
string varName = varAst.VariablePath.UserPath;
var varPath = varAst.VariablePath;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the type name instead of var here

@@ -2329,7 +2330,8 @@ internal string GetParamTextWithDollarUsingHandling(IEnumerator<VariableExpressi
// We are done processing the current ParameterAst
if (astStartOffset >= endOffset) { break; }

string varName = varAst.VariablePath.UserPath;
var varPath = varAst.VariablePath;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

@@ -2374,7 +2374,8 @@ private string GetConvertedScript(out List<string> newParameterNames, out List<o

foreach (var varAst in usingVariables)
{
string varName = varAst.VariablePath.UserPath;
var varPath = varAst.VariablePath;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

@rjmholt
Copy link
Collaborator

rjmholt commented Oct 5, 2021

Not sure what the state of testing is for $using: vars, but would be good if we had some to cover the code path this change affects

@ghost ghost removed the Review - Needed The PR is being reviewed label Oct 5, 2021
@rjmholt rjmholt requested a review from PaulHigin October 5, 2021 22:19
@rjmholt
Copy link
Collaborator

rjmholt commented Oct 5, 2021

Tagging @PaulHigin for review as well

@dwtaber
Copy link
Contributor Author

dwtaber commented Oct 6, 2021

Git/GitHub novice question: when updating from the master branch, I should have used a fast-forward merge to avoid creating a separate merge commit, right? How much of a problem is it that I, uh, didn't do that?

@iSazonov
Copy link
Collaborator

iSazonov commented Oct 6, 2021

@dwtaber Never mind - we use "squash and merge" to get one commit in main branch.

Copy link
Contributor

@PaulHigin PaulHigin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good to me.

@rjmholt rjmholt enabled auto-merge (squash) October 6, 2021 17:43
@rjmholt rjmholt merged commit 53ac646 into PowerShell:master Oct 6, 2021
@dwtaber dwtaber deleted the InvokeCommandFixUsingExpressionsWithQualifiedVarPath branch October 6, 2021 20:56
@iSazonov iSazonov added the CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log label Oct 7, 2021
@iSazonov iSazonov modified the milestones: 7.2.0-preview.10, 7.2.0-rc.1 Oct 7, 2021
@dwtaber
Copy link
Contributor Author

dwtaber commented Oct 28, 2021

@rjmholt, judging by its file history, it looks like System.Management.Automation/engine/parser/ast.cs wasn't updated during the merge, so the bug addressed by this PR still exists.

@daxian-dbw daxian-dbw removed this from the 7.2.0-rc.1 milestone Oct 28, 2021
@daxian-dbw
Copy link
Member

daxian-dbw commented Oct 28, 2021

@dwtaber Changes from this PR exists in the master branch. The PR will not be included in 7.2.0-rc.1 though. It will be included in 7.3.0-preview.1.

@dwtaber
Copy link
Contributor Author

dwtaber commented Oct 28, 2021

@dwtaber Changes from this PR exists in the master branch. The PR will not be included in 7.2.0-rc.1 though. It will be included in 7.3.0-preview.1.

Ah, okay. Thanks for clarifying!

@ghost
Copy link

ghost commented Dec 16, 2021

🎉v7.3.0-preview.1 has been released which incorporates this pull request.:tada:

Handy links:

@ImportTaste
Copy link
Contributor

ImportTaste commented Dec 23, 2021

I really wish this had made it into the stable release of 7.2, I try to avoid using preview-exclusive stuff in my code, so having to wait for 7.3's stable release really sucks.

Is there any chance this could be slipped into a 7.2 build, i.e. 7.2.2?

@TravisEz13
Copy link
Member

@PowerShell/powershell-maintainers
We only take security fixes and regression to LTS. This is appropriate for 7.3. Rejecting back-port.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log
Projects
None yet
8 participants