Skip to content

Conversation

@yolocs
Copy link
Contributor

@yolocs yolocs commented Mar 7, 2018

Description

Fix #5506

Checklist

Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a snippet about this change to your changelog to ensure it is picked up in the next release: https://github.com/Azure/azure-powershell/blob/preview/src/ResourceManager/ContainerInstance/ChangeLog.md

Copy link
Contributor

Choose a reason for hiding this comment

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

Please change this into two parameter sets (it is better to do validation over parameter sets rather than throwing at runtime). You should have:
New-AzureRmContainerGroup
[-ResourceGroupName]
[-Name]
[-Image]
[-RegistryCredential ]
[-Location ]
[-OsType ]
[-RestartPolicy ]
[-Cpu ]
[-MemoryInGB ]
[-IpAddressType ]
[-Port <Int32[]>]
[-Command ]
[-EnvironmentVariable ]
[-RegistryServerDomain ]
[-Tag ]
[-DefaultProfile ]
[-WhatIf]
[-Confirm]
[]

and

New-AzureRmContainerGroup
[-ResourceGroupName]
[-Name]
[-Image]
[ -RegistryCredential ]
-AzureFileVolumeShareName
-AzureFileVolumeAccountCredential
-AzureFileVolumeMountPath
[-Location ]
[-OsType ]
[-RestartPolicy ]
[-Cpu ]
[-MemoryInGB ]
[-IpAddressType ]
[-Port <Int32[]>]
[-Command ]
[-EnvironmentVariable ]
[-Tag ]
[-DefaultProfile ]
[-WhatIf]
[-Confirm]
[]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@maddieclayton I have doubts here. What if we have another set of parameters that require validation but those parameters can also be used along with these 'AzureFile' parameters? That's exactly what happened for the issue associated.

Copy link
Contributor

Choose a reason for hiding this comment

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

As long as we can reasonable validate with parameter sets that is the best way to do this validation - in your proposed version, a user looking at the docs would have no idea that a set of parameters are required if one is provided, which a bad experience, especially while scripting. If we have an issue with this in the future we can look at it again then.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But in this case, the bad experience is already happening for registry related parameters. When a registry server is specified, the registry credential should also be specified. And now I can only validate that in runtime. What's the guideline here to determine which parameters to be prioritized to put into a parameter set? e.g. azure file parameters vs. registry paramters

Copy link
Contributor

@maddieclayton maddieclayton Mar 8, 2018

Choose a reason for hiding this comment

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

A couple of notes, as I had not seen this code:

You should make Location mandatory instead of throwing an exception at runtime.
You should have these parameter sets to get rid of runtime validation over RegistryServer:
New-AzureRmContainerGroup
[-ResourceGroupName]
[-Name]
[-Image]
[-RegistryCredential ]
[-Location ]
[-OsType ]
[-RestartPolicy ]
[-Cpu ]
[-MemoryInGB ]
[-IpAddressType ]
[-Port <Int32[]>]
[-Command ]
[-EnvironmentVariable ]
[-Tag ]
[-DefaultProfile ]
[-WhatIf]
[-Confirm]

New-AzureRmContainerGroup
[-ResourceGroupName]
[-Name]
[-Image]
-RegistryServerDomain
-RegistryCredential
[-Location ]
[-OsType ]
[-RestartPolicy ]
[-Cpu ]
[-MemoryInGB ]
[-IpAddressType ]
[-Port <Int32[]>]
[-Command ]
[-EnvironmentVariable ]
[-Tag ]
[-DefaultProfile ]
[-WhatIf]
[-Confirm]

The third validation you should keep, as it cannot be done through parameter set validation. The fourth validation could be moved into parameter validation using validatescript, but this is not required. The whole purpose of parameter sets is to ensure users can figure out how to run cmdlets without having to use trial and error.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that should eliminate all of the parameter validation that can be done on the parameter set level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't find any example using ValidateScript in c#. Do you have any example?

Copy link
Contributor

Choose a reason for hiding this comment

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

The syntax should be pretty much the same for both PowerShell and C# syntax: https://powershell.org/2013/05/21/validatescript-for-beginners/. Basically, you want the script to return true if the parameter is valid, and false otherwise. Error Message can be given like this: https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.validatescriptattribute.errormessage?view=pscore-6.0.0&viewFallbackFrom=powershellsdk-1.1.0

Copy link
Contributor

Choose a reason for hiding this comment

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

This is not a blocking change for your PR, so it is up to you if you want to make this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good to know. It seems it requires a recent version of powershell sdk.
Anyway, I add back parameter set for azure file.

Copy link
Contributor

Choose a reason for hiding this comment

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

remove new validation, should be fixed by parameter sets.

Copy link
Contributor

Choose a reason for hiding this comment

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

regenerate this file once parameter sets are fixed.

@yolocs
Copy link
Contributor Author

yolocs commented Mar 12, 2018

@maddieclayton ping

Copy link
Member

@cormacpayne cormacpayne left a comment

Choose a reason for hiding this comment

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

@yolo3301 can we add test coverage to prevent the linked issue from resurfacing in the future?

Copy link
Member

Choose a reason for hiding this comment

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

@yolo3301 you don't need this version header -- you can just put this content under the ## Current Release header


[Parameter(
Mandatory = true,
ParameterSetName = CreateContainerGroupWithRegistryParamSet,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add the third parameter set we discussed in preview comments? Looks like you only have two at the moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to but I don't think it can work. The problem is there is no unique mandatory parameter for Registry. You might think RegistryServer should be the unique mandatory one. But we actually support omitting it if the Image is from azure container registry, which means RegistryServer is not mandatory. Am I right?

Copy link
Contributor Author

@yolocs yolocs Mar 12, 2018

Choose a reason for hiding this comment

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

You might also argue I can use RegistryCredential as the unique mandatory parameter. However, if that's present, there is nothing else to validate because RegistryServer is optional as described above.

Copy link
Contributor

Choose a reason for hiding this comment

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

Your new parameter set would have both RegistryServer and RegistryCredential mandatory. Any case where RegistryServer is given, RegistryCredential must be also given, and this parameter set covers this case. Any other case where RegistryServer is not specified will be covered by the first parameter set (which will not contain RegistryServer and RegistryCredential will be optional).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In my test, it doesn't validate Registry parameters at all. Here are the parameter sets:

SYNTAX
    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> [-RegistryCredential <pscredential>] [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] [-MemoryInGB
    <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-RegistryServerDomain <string>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]
    [<CommonParameters>]

    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -RegistryCredential <pscredential> -RegistryServerDomain <string> [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}]
    [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]
    [<CommonParameters>]

    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -AzureFileVolumeShareName <string> -AzureFileVolumeAccountCredential <pscredential> -AzureFileVolumeMountPath <string> [-RegistryCredential <pscredential>]
    [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>]
    [-RegistryServerDomain <string>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

With above parameter sets, if I have:

New-AzureRmContainerGroup -ResourceGroupName $resourceGroupName -Name $containerGroupName -Image $image -RegistryCredential $registryCredential

It won't fail while I expect it asks me to give -RegistryServer. On the other hand, if I have:

New-AzureRmContainerGroup -ResourceGroupName $resourceGroupName -Name $containerGroupName -Image $image -RegistryServer "registry.io"

It gives me runtime error while I expect a parameter set check.

Any idea?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is supported. Registry parameters can be used along with FileVolume ones.
Back to my first comment, in our case, almost every parameter can be used with other parameters. The validation needs happen in a way like: when parameter A is present, parameter B must be present too. But at the same time A & B can be used with every other parameter.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, these should be your parameter sets then:

PS1: All parameters that don't need validation (don't include FileVolume or Registry) - all parameters are optional and this is the default
PS2: All parameters that don't need validation, and the two registry parameters as required.
PS3: All parameters that don't need validation, and the FileVolume parameters as required.
PS4: All parameters that don't need validation, and both the registry and FileVolume parameters as required.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK. Confirming the following is what you suggested:

SYNTAX
    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType
    {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -RegistryServerDomain <string> -RegistryCredential <pscredential> [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never |
    OnFailure}] [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>]
    [-WhatIf] [-Confirm]  [<CommonParameters>]

    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -RegistryServerDomain <string> -RegistryCredential <pscredential> -AzureFileVolumeMountPath <string> -AzureFileVolumeShareName <string>
    -AzureFileVolumeAccountCredential <pscredential> [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port
    <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -AzureFileVolumeMountPath <string> -AzureFileVolumeShareName <string> -AzureFileVolumeAccountCredential <pscredential> [-Location <string>] [-OsType
    {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag
    <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

With these parameter sets, the following valid commands won't work as expected:

New-AzureRmContainerGroup -ResourceGroupName $resourceGroupName -Name $containerGroupName -Image $image -RegistryCredential $registryCredential 
# Parameter set cannot be resolved using the specified named parameters.

New-AzureRmContainerGroup -ResourceGroupName $resourceGroupName -Name $containerGroupName -Image $image -RegistryServerDomain "abc.io"
# Parameter set cannot be resolved using the specified named parameters.

New-AzureRmContainerGroup -ResourceGroupName $resourceGroupName -Name $containerGroupName -Image $image -RegistryCredential $registryCredential -AzureFileVolumeShareName $shareName -AzureFileVolumeAccountCredential $accountCredential -AzureFileVolumeMountPath $mountPath
# Cannot process command because of one or more missing mandatory parameters: RegistryServerDomain.

The problem is -RegistryServer is not always required. And -RegistryCredential is mandatory if and only if -RegistryServer is present. When -RegistryServer is not present, -RegistryCredential is optional. So I also tried the following parameter sets:

SYNTAX
    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> [-RegistryCredential <pscredential>] [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu
    <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf]
    [-Confirm]  [<CommonParameters>]

    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -RegistryServerDomain <string> -RegistryCredential <pscredential> [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy
    {Always | Never | OnFailure}] [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag <hashtable>] [-DefaultProfile
    <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -RegistryServerDomain <string> -RegistryCredential <pscredential> -AzureFileVolumeMountPath <string> -AzureFileVolumeShareName <string>
    -AzureFileVolumeAccountCredential <pscredential> [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel
    <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

    New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -AzureFileVolumeMountPath <string> -AzureFileVolumeShareName <string> -AzureFileVolumeAccountCredential <pscredential>
    [-RegistryCredential <pscredential>] [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] [-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port
    <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] [-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

It can make the above 2 commands work as expected. But there is still one command doesn't work as expected:

New-AzureRmContainerGroup -ResourceGroupName $resourceGroupName -Name $containerGroupName -Image $image -RegistryServerDomain "abc.io"
# Parameter set cannot be resolved using the specified named parameters.
# This one doesn't give the right error message, it should complain -RegistryCredential can't be null

Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, as PowerShell can't resolve the parameter set, you should keep the validation for registryserverdomain/registrycredential in the executecmdlet statement. Please keep the individual sets for the Volume share cmdlets:

New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> [-RegistryServerDomain <string>] `
[-RegistryCredential <pscredential>] [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] `
[-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] `
[-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

New-AzureRmContainerGroup [-ResourceGroupName] <string> [-Name] <string> [-Image] <string> -AzureFileVolumeMountPath <string> `
-AzureFileVolumeShareName <string> -AzureFileVolumeAccountCredential <pscredential> [-RegistryServerDomain <string>] `
[-RegistryCredential <pscredential>] [-Location <string>] [-OsType {Linux | Windows}] [-RestartPolicy {Always | Never | OnFailure}] [-Cpu <int>] `
[-MemoryInGB <double>] [-IpAddressType {Public}] [-DnsNameLabel <string>] [-Port <int[]>] [-Command <string>] [-EnvironmentVariable <hashtable>] `
[-Tag <hashtable>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm]  [<CommonParameters>]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that's what's already in the PR.

maddieclayton
maddieclayton previously approved these changes Mar 19, 2018
@maddieclayton
Copy link
Contributor

@maddieclayton maddieclayton merged commit 6a893ee into Azure:preview Mar 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants