Skip to content

Move wiki changes to docs #6427

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

Merged
merged 2 commits into from
Jun 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ The Azure PowerShell Developer Guide was created to help with the development an
- [After Development](#after-development)
- [Misc](#misc)
- [Publish to PowerShell Gallery](#publish-to-powershell-gallery)
- [AsJob Parameters](#asjob-parameters)
- [AsJob Parameter](#asjob-parameter)
- [Argument Completers](#argument-completers)
- [Resource Group Completer](#resource-group-completers)
- [Location Completer](#location-completer)
Expand All @@ -52,8 +52,6 @@ The following prerequisites should be completed before contributing to the Azure

- Install [Visual Studio 2015](https://www.visualstudio.com/downloads/)
- Install the latest version of [Git](https://git-scm.com/downloads)
- Install the latest version of [WiX](http://wixtoolset.org/releases/)
- After installation, ensure that the path to "WiX Toolset\bin" has been added to your `PATH` environment variable
- Install the [`platyPS` module](https://github.com/Azure/azure-powershell/blob/preview/documentation/development-docs/help-generation.md#installing-platyps)
- Set the PowerShell [execution policy](https://technet.microsoft.com/en-us/library/ee176961.aspx) to **Unrestricted** for the following versions of PowerShell:
- `C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe`
Expand Down Expand Up @@ -116,8 +114,6 @@ By default, we build the `dll-Help.xml` files (used to display the help content
msbuild build.proj /p:SkipHelp=true
```

_Note_: when [updating the installer](#updating-the-installer), you **should not** skip the help generation step, as it removes the `dll-Help.xml` files from the wxi file.

## Running Tests

With the same terminal open from the previous section, run the cmdlet `Invoke-CheckinTests` to run all of the tests in the project
Expand All @@ -142,10 +138,9 @@ Before development, you must meet with the Azure PowerShell team to have a desig

Before submitting a design review, please be sure that you have read the [Azure PowerShell Design Guidelines](./azure-powershell-design-guidelines.md) document.

Please email the **azdevxpsdr** alias to set up this review and include the following information:
- Short description of the top-level scenarios
- Proposed cmdlet syntax
- Sample output of cmdlets
Please submit a design review here: https://github.com/Azure/azure-powershell-cmdlet-review-pr

_Note_: You will need to be part of the GitHub Azure org to see this repository. Please go to [this link](aka.ms/azuregithub) to become part of the Azure org.

We recommend using the `platyPS` module to easily generate markdown files that contains the above information and including the files in the email.

Expand Down
223 changes: 139 additions & 84 deletions documentation/development-docs/piping-in-powershell.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,141 @@
# Piping in PowerShell
# Azure PowerShell Piping Scenarios

There are two main scenarios that we wish to enable in cmdlets for Azure PowerShell:
- piping by value using an `InputObject` parameter
- piping by property name using a `ResourceId` parameter

## Using the `InputObject` parameter

### Short explanation
For all resources, `InputObject` should be implemented for the Remove/Set/Update cmdlets (and any other cmdlet where an existing resource is being operated on). The implementation of this will be a new parameter set:

```powershell
Remove/Set/Update-AzureRm<ExampleResource> -InputObject <TypeOfExampleResource> <Other parameters that cannot be obtained from TypeOfExampleResource>
```

For all child resources, `InputObject` should also be implemented for the Get/New cmdlets. The implementation of this will be a new parameter set:

```powershell
Get/New-AzureRm<ExampleResource> -ParentObject <TypeOfParentOfExampleResource> <Other parameters that cannot be obtained from TypeOfParentOfExampleResource>
```

### Long explanation
This scenario should be used when piping objects around within the same module. For example, if you have a set of `Get-AzureRmFoo`, `Remove-AzureRmFoo`, and `Set-AzureRmFoo` cmdlets, the `Remove-AzureRmFoo` and `Set-AzureRmFoo` cmdlets should have a parameter set that takes the `InputObject` parameter of type `PSFoo` so that a user can do the following:

```powershell
# --- Piping scenario ---
# Setting and removing an individual object
Get-AzureRmFoo -Name "FooName" -ResourceGroupName "RG" | Set-AzureRmFoo <additional parameters>
Get-AzureRmFoo -Name "FooName" -ResourceGroupName "RG" | Remove-AzureRmFoo

# Setting and removing a collection of objects
Get-AzureRmFoo | Set-AzureRmFoo <additional parameters>
Get-AzureRmFoo | Remove-AzureRmFoo


# --- Non-piping scenario ---
# Setting and removing an individual object
$foo = Get-AzureRmFoo -Name "FooName" -ResourceGroupName "RG"
Set-AzureRmFoo -InputObject $foo <additional parameters>
Remove-AzureRmFoo -InputObject $foo

# Setting and removing a collection of objects
Get-AzureRmFoo | ForEach-Object { Set-AzureRmFoo -InputObject $_ <additional parameters> }
Get-AzureRmFoo | ForEach-Object { Remove-AzureRmFoo -InputObject $_ }
```

Another time that this scenario applies is when you have cmdlets for child resources that need information about the parent (top-level) resource. For example you can pipe in the whole parent object to the `New-AzureRmFooBar` and `Get-AzureRmFooBar` cmdlets to get the child resources, and then pipe the child resource object to the `Remove-AzureRmFooBar` and `Set-AzureRmFooBar` cmdlets.

```powershell
# --- Piping scenario ---
# Getting all of child resources from all of the parent resources and removing them
Get-AzureRmFoo | Get-AzureRmFooBar | Remove-AzureRmFooBar

# Getting all of the child resources from all of the parent resources in a resource group and removing them
Get-AzureRmFoo -ResourceGroupName "RG" | Get-AzureRmFooBar | Remove-AzureRmFooBar

# Getting all of the child resources from a specific parent resource and removing them
Get-AzureRmFoo -ResourceGroupName "RG" -Name "FooName" | Get-AzureRmFooBar | Remove-AzureRmFooBar


# --- Non-piping scenario ---
# Getting all of the child resources from a specific parent resource and removing them
$foo = Get-AzureRmFoo -ResourceGroupName "RG" -Name "FooName"
$fooBar = Get-AzureRmFooBar -InputObject $foo
Remove-AzureRmFooBar -InputObject $fooBar
```

## Using the `ResourceId` parameter

### Short explanation
For all resources, `ResourceId` should be implemented for the Remove/Set/Update cmdlets (and any other cmdlet where an existing resource is being operated on). The implementation of this will be a new parameter set:

```powershell
Remove/Set/Update-AzureRm<ExampleResource> -ResourceId <string (accepts ExampleResource ResourceId> <Other parameters that cannot be obtained from ExampleResource ResourceId>
```

For all child resources, `ResourceId` should also be implemented for the Get/New cmdlets. The implementation of this will be a new parameter set:

```powershell
Get/New-AzureRm<ExampleResource> -ParentResourceId <string (accepts ResourceId of the parent of ExampleResource> <Other parameters that cannot be obtained from the ResourceId of the parent of ExampleResource>
```

### Long explanation

In this scenario, we are using the generic cmdlets found in the `AzureRM.Resources` module. These cmdlets, `Find-AzureRmResource` and `Get-AzureRmResource`, return a `PSCustomObject` that has a `ResourceId` property, which is the unique identifier for the given resource. Since this identifier can parsed to get the name and resource group name for a top-level resource, we can create a parameter set that has a `ResourceId` parameter that accepts its value from the pipeline by property name, allowing us to accept piping from these generic cmdlets.

```powershell
# --- Piping scenario ---
# Remove all Foo objects in the current subscription
Find-AzureRmResource -ResourceType Microsoft.Foo/foo | Remove-AzureRmFoo

# Remove all Foo objects in a given resource group
Find-AzureRmResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | Remove-AzureRmFoo

# Remove a specific Foo object
Find-AzureRmResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | Remove-AzureRmFoo


# -- Non-piping scenario ---
# Removing all Foo objects in the current subscription
Find-AzureRmResource -ResourceType Microsoft.Foo/foo | ForEach-Object { Remove-AzureRmFoo -ResourceId $_.ResourceId }

# Remove all Foo objects in a given resource group
Find-AzureRmResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | ForEach-Object { Remove-AzureRmFoo -ResourceId $_.ResourceId }

# Remove a specific Foo object
Find-AzureRmResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | ForEach-Object { Remove-AzureRmFoo -ResourceId $_.ResourceId }
```

To implement this scenario, please see the [`ResourceIdentifier`](https://github.com/Azure/azure-powershell/blob/preview/src/ResourceManager/Common/Commands.ResourceManager.Common/Utilities/Models/ResourceIdentifier.cs) class in the `Commands.ResourceManager.Common` project. This class will allow you to create a `ResourceIdentifier` object that accepts a `ResourceId` string in its constructor and has properties `ResourceName`, `ResourceGroupName`, and others.

## Summary
For all Remove/Set/Update cmdlets (and any other cmdlet where an existing resource is being operated on), you will have three parameter sets (and potentially a multiple of three if you have initially have multiple parameter sets):
```powershell
Remove/Set/Update-AzureRm<ExampleResource> <parameters that are required to identify ExampleResource> <Other parameters>
Remove/Set/Update-AzureRm<ExampleResource> -InputObject <TypeOfExampleResource> <Other parameters that cannot be obtained from TypeOfExampleResource>
Remove/Set/Update-AzureRm<ExampleResource> -ResourceId <string (accepts ExampleResource ResourceId> <Other parameters that cannot be obtained from ExampleResource ResourceId>
```
For example, for child resource "Widget" with parent "Foo", there will be these three parameter sets for Remove:
```powershell
Remove-AzureRmWidget -ResourceGroupName <string> -FooName <string> -Name <string>
Remove-AzureRmWidget -InputObject <Widget>
Remove-AzureRmWidget -ResourceId <string>
```
For all child resources, Get/New cmdlets will also have these three parameter sets:
```powershell
Get/New-AzureRm<ExampleResource> <parameters needed to identify/create ExampleResource>
Get-AzureRm<ExampleResource> -InputObject <TypeOfParentOfExampleResource> <Other parameters that cannot be obtained from TypeOfParentOfExampleResource>
Get/New-AzureRm<ExampleResource> -ResourceId <string (accepts ResourceId of the parent of ExampleResource> <Other parameters that cannot be obtained from the ResourceId of the parent of ExampleResource>
```
For example, for child resource "Widget" with parent "Foo", there will be these three parameter sets for New:
```powershell
New-AzureRmWidget -ResourceGroupName <string> -FooName <String> -Name <string>
New-AzureRmWidget -WidgetObject <Foo> -Name <string>
New-AzureRmWidget -WidgetResourceId <string> -Name <string>
```

# Piping in PowerShell (additional information)

## Understanding Piping

Expand Down Expand Up @@ -107,88 +244,6 @@ public override void ExecuteCmdlet()
}
```

## Azure PowerShell Piping Scenarios

There are two main scenarios that we wish to enable in cmdlets for Azure PowerShell:
- piping by value using an `InputObject` parameter
- piping by property name using a `ResourceId` parameter

### Using the `InputObject` parameter

This scenario should be used when piping objects around within the same module. For example, if you have a set of `Get-AzureRmFoo`, `Remove-AzureRmFoo`, and `Set-AzureRmFoo` cmdlets, the `Remove-AzureRmFoo` and `Set-AzureRmFoo` cmdlets should have a parameter set that takes the `InputObject` parameter of type `PSFoo` so that a user can do the following:

```powershell
# --- Piping scenario ---
# Setting and removing an individual object
Get-AzureRmFoo -Name "FooName" -ResourceGroupName "RG" | Set-AzureRmFoo <additional parameters>
Get-AzureRmFoo -Name "FooName" -ResourceGroupName "RG" | Remove-AzureRmFoo

# Setting and removing a collection of objects
Get-AzureRmFoo | Set-AzureRmFoo <additional parameters>
Get-AzureRmFoo | Remove-AzureRmFoo


# --- Non-piping scenario ---
# Setting and removing an individual object
$foo = Get-AzureRmFoo -Name "FooName" -ResourceGroupName "RG"
Set-AzureRmFoo -InputObject $foo <additional parameters>
Remove-AzureRmFoo -InputObject $foo

# Setting and removing a collection of objects
Get-AzureRmFoo | ForEach-Object { Set-AzureRmFoo -InputObject $_ <additional parameters> }
Get-AzureRmFoo | ForEach-Object { Remove-AzureRmFoo -InputObject $_ }
```

Another time that this scenario applies is when you have cmdlets for child resources that need information about the parent (top-level) resource. For example you can pipe in the whole parent object to the `New-AzureRmFooBar` and `Get-AzureRmFooBar` cmdlets to get the child resources, and then pipe the child resource object to the `Remove-AzureRmFooBar` and `Set-AzureRmFooBar` cmdlets.

```powershell
# --- Piping scenario ---
# Getting all of child resources from all of the parent resources and removing them
Get-AzureRmFoo | Get-AzureRmFooBar | Remove-AzureRmFooBar

# Getting all of the child resources from all of the parent resources in a resource group and removing them
Get-AzureRmFoo -ResourceGroupName "RG" | Get-AzureRmFooBar | Remove-AzureRmFooBar

# Getting all of the child resources from a specific parent resource and removing them
Get-AzureRmFoo -ResourceGroupName "RG" -Name "FooName" | Get-AzureRmFooBar | Remove-AzureRmFooBar


# --- Non-piping scenario ---
# Getting all of the child resources from a specific parent resource and removing them
$foo = Get-AzureRmFoo -ResourceGroupName "RG" -Name "FooName"
$fooBar = Get-AzureRmFooBar -InputObject $foo
Remove-AzureRmFooBar -InputObject $fooBar
```

### Using the `ResourceId` parameter

In this scenario, we are using the generic cmdlets found in the `AzureRM.Resources` module. These cmdlets, `Find-AzureRmResource` and `Get-AzureRmResource`, return a `PSCustomObject` that has a `ResourceId` property, which is the unique identifier for the given resource. Since this identifier can parsed to get the name and resource group name for a top-level resource, we can create a parameter set that has a `ResourceId` parameter that accepts its value from the pipeline by property name, allowing us to accept piping from these generic cmdlets.

```powershell
# --- Piping scenario ---
# Remove all Foo objects in the current subscription
Find-AzureRmResource -ResourceType Microsoft.Foo/foo | Remove-AzureRmFoo

# Remove all Foo objects in a given resource group
Find-AzureRmResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | Remove-AzureRmFoo

# Remove a specific Foo object
Find-AzureRmResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | Remove-AzureRmFoo


# -- Non-piping scenario ---
# Removing all Foo objects in the current subscription
Find-AzureRmResource -ResourceType Microsoft.Foo/foo | ForEach-Object { Remove-AzureRmFoo -ResourceId $_.ResourceId }

# Remove all Foo objects in a given resource group
Find-AzureRmResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | ForEach-Object { Remove-AzureRmFoo -ResourceId $_.ResourceId }

# Remove a specific Foo object
Find-AzureRmResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | ForEach-Object { Remove-AzureRmFoo -ResourceId $_.ResourceId }
```

To implement this scenario, please see the [`ResourceIdentifier`](https://github.com/Azure/azure-powershell/blob/preview/src/ResourceManager/Common/Commands.ResourceManager.Common/Utilities/Models/ResourceIdentifier.cs) class in the `Commands.ResourceManager.Common` project. This class will allow you to create a `ResourceIdentifier` object that accepts a `ResourceId` string in its constructor and has properties `ResourceName`, `ResourceGroupName`, and others.

## More Information

For more information on piping, see the article ["Understanding the Windows PowerShell Pipeline"](https://msdn.microsoft.com/en-us/powershell/scripting/getting-started/fundamental/understanding-the-windows-powershell-pipeline).
For more information on piping, see the article ["Understanding the Windows PowerShell Pipeline"](https://msdn.microsoft.com/en-us/powershell/scripting/getting-started/fundamental/understanding-the-windows-powershell-pipeline).