Skip to content

Policy parameters support in New-AzureRmPolicyDefinition and New-AzureRmPolicyAssignment #3476

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 18 commits into from
Feb 16, 2017

Conversation

luanshixia
Copy link
Contributor

@luanshixia luanshixia commented Feb 7, 2017

Description

Added support for policy parameters to the 2 cmdlets to use the feature provided by API version 2016-12-01.


This checklist is used to make sure that common guidelines for a pull request are followed. You can find a more complete discussion of PowerShell cmdlet best practices here.

General Guidelines

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.
  • The pull request does not introduce breaking changes (unless a major version change occurs in the assembly and module).

Testing Guidelines

  • Pull request includes test coverage for the included changes.
  • PowerShell scripts used in tests should do any necessary setup as part of the test or suite setup, and should not use hard-coded values for locations or existing resources.

Cmdlet Signature Guidelines

  • New cmdlets that make changes or have side effects should implement ShouldProcess and have SupportShouldProcess=true specified in the cmdlet attribute. You can find more information on ShouldProcess here.
  • Cmdlet specifies OutputType attribute if any output is produced - if the cmdlet produces no output, it should implement a PassThru parameter.

Cmdlet Parameter Guidelines

  • Parameter types should not expose types from the management library - complex parameter types should be defined in the module.
  • Cmdlet parameter sets should be mutually exclusive - each parameter set must have at least one mandatory parameter not in other parameter sets.
  • Complex parameter types are discouraged - a parameter type should be simple types as often as possible. If complex types are used, they should be shallow and easily creatable from a constructor or another cmdlet.

@azurecla
Copy link

azurecla commented Feb 7, 2017

Hi @luanshixia, I'm your friendly neighborhood Azure Pull Request Bot (You can call me AZPRBOT). Thanks for your contribution!


It looks like you're working at Microsoft (wayan). If you're full-time, we DON'T require a contribution license agreement.



If you are a vendor, DO please sign the electronic contribution license agreement. It will take 2 minutes and there's no faxing! https://cla.azure.com.

TTYL, AZPRBOT;

@azuresdkci
Copy link

Can one of the admins verify this patch?

@@ -54,6 +61,19 @@ public class NewAzurePolicyAssignmentCmdlet : PolicyAssignmentCmdletBase
public PSObject PolicyDefinition { get; set; }

/// <summary>
/// Gets or sets the policy assignment policy parameter object.
/// </summary>
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "The pollicy parameter object.")]
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo in the help message "pollicy" should be "policy"

/// <summary>
/// Gets or sets the policy assignment policy parameter file or string.
/// </summary>
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "The pollicy parameter file or string.")]
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo in the help message "pollicy"

@@ -112,11 +132,88 @@ private JToken GetResource()
{
DisplayName = this.DisplayName ?? null,
PolicyDefinitionId = this.PolicyDefinition.Properties["policyDefinitionId"].Value.ToString(),
Scope = this.Scope
Scope = this.Scope,
Parameters = GetParameters()
Copy link
Contributor

Choose a reason for hiding this comment

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

we usually scope the function calls, so this should be this.GetParameters()

/// Gets or sets the policy assignment policy parameter object.
/// </summary>
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "The pollicy parameter object.")]
public Hashtable PolicyParameterObject { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

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

We should have validation so that user cannot specify both PolicyParameterObject and PolicyParameters.
This can be implemented using parameter sets.

/// </summary>
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "The pollicy parameter file or string.")]
[ValidateNotNullOrEmpty]
public string PolicyParameters { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we rename this to PolicyParametersFile?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just confirmed with Mike that it is the expected behavior.

// Load parameters from local file or literal
if (PolicyParameters != null)
{
string policyParameterFilePath = this.TryResolvePath(PolicyParameters);
Copy link
Contributor

@maphad maphad Feb 8, 2017

Choose a reason for hiding this comment

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

I think it is confusing to use a single parameter as maybe a file name or maybe a string representing parameters.
We should explicitly make them two separate parameters. So in total we should have three parameters:
PolicyParameters
PolicyParametersFile
PolicyParametersObject.
Each should be in its own ParameterSet so that user can only specify one of them.

Were you specifically asked to use just two parameters?

Copy link
Contributor

Choose a reason for hiding this comment

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

For how to use ParameterSets u can refer to this documentation https://msdn.microsoft.com/en-us/library/dd878348(v=vs.85).aspx. Also several of our existing cmdlets use parameter sets.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the 1st one: Just confirmed with Mike that it is the expected behavior.
For the 2nd one: Yes will do that.

{
return null;
}
else
Copy link
Contributor

Choose a reason for hiding this comment

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

No need of else here since you are returning control from if


object IDynamicParameters.GetDynamicParameters()
{
if (PolicyDefinition != null)
Copy link
Contributor

Choose a reason for hiding this comment

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

scope it as this.PolicyDefinition, everywhere

/// </summary>
private JToken GetParametersObject()
{
string parametersFilePath = this.TryResolvePath(this.Parameters);
Copy link
Contributor

Choose a reason for hiding this comment

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

As above I think we shouldn't use the same parameter as maybe a filePath or a parameter. It would be cleaner to have two separate parameters in two different parameter sets.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just confirmed with Mike that it is the expected behavior.

}
};

return policyassignmentObject.ToJToken();
}

object IDynamicParameters.GetDynamicParameters()
Copy link
Contributor

Choose a reason for hiding this comment

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

who calls this method and can u point me to how dynamic parameters work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This interface method is called by the PowerShell engine (thus a callback), so PowerShell can know what parameters are defined dynamically in the cmdlet and allow users to provide values for them.

@@ -113,7 +120,8 @@ private JToken GetResource()
{
Description = this.Description ?? null,
DisplayName = this.DisplayName ?? null,
PolicyRule = JObject.Parse(GetPolicyRuleObject().ToString())
PolicyRule = JObject.Parse(GetPolicyRuleObject().ToString()),
Parameters = this.Parameters == null ? null : JObject.Parse(GetParametersObject().ToString())
Copy link
Contributor

Choose a reason for hiding this comment

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

this.GetParametersObject

@@ -15,6 +15,7 @@
namespace Microsoft.Azure.Commands.ResourceManager.Cmdlets.Entities.Policy
{
using Newtonsoft.Json;
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like it has 3 commits. We should squash changes to a single commit, so that it is easy to revert the entire change if 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.

This can be a 1-click when merging on this page, though I don't have permission to do that now.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok please squash before merging then.

return File.Exists(parametersFilePath)
? JToken.FromObject(FileUtilities.DataStore.ReadFileAsText(parametersFilePath))
: JToken.FromObject(this.Policy);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

You can add scenario tests once you have addressed the PR comments.
Also get this PR reviewed by vivsrini.

@cormacpayne
Copy link
Member

@azuresdkci add to whitelist

}
};

return policyassignmentObject.ToJToken();
}

object IDynamicParameters.GetDynamicParameters()
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't look like it belongs here. Can we move this out to a common/util file?

Copy link
Contributor Author

@luanshixia luanshixia Feb 8, 2017

Choose a reason for hiding this comment

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

This is the implementation of the interface IDynamicParameters, which the class conforms to.


/// <summary>
/// Creates a policy assignment.
/// </summary>
[Cmdlet(VerbsCommon.New, "AzureRmPolicyAssignment"), OutputType(typeof(PSObject))]
public class NewAzurePolicyAssignmentCmdlet : PolicyAssignmentCmdletBase
public class NewAzurePolicyAssignmentCmdlet : PolicyAssignmentCmdletBase, IDynamicParameters
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 scenario tests/moq tests for both these cmdlets

/// The parameters declaration.
/// </summary>
[JsonProperty(Required = Required.Default)]
public JObject Parameters { get; set; }
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 please confirm that there are no changes required for other policy cmdlets? i.e.,

  1. Get/set/remove policy definition works with and without parameters
  2. Get/set/remove policy assignment works with and without parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

AFAIK, no impact at this time.

/// </summary>
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "The parameters for policy definition. This can either be a path to a file name containing the parameters declaration, or the parameters declaration as string.")]
[ValidateNotNullOrEmpty]
public string Parameters { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

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

PolicyDefinitionParameters?

[Parameter(ParameterSetName = PolicyParametersStringParameterSetName,
Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = "The policy parameters file path or policy parameters string.")]
[ValidateNotNullOrEmpty]
public string PolicyParameters { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

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

PolicyAssignmentParameters?

TBH, the names are confusing as-is (what is the difference between parameters in policy def vs policy assignment?)

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, please ensure the help files are updated accordingly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For 1: So the parameters in policy def are declarations and those in policy assignment are actual values. I know the names are confusing, but I have confirmed with Mike about these names.
For 2: Will do that.

@@ -59,6 +59,13 @@ public class NewAzurePolicyDefinitionCmdlet : PolicyDefinitionCmdletBase
public string Policy { get; set; }

/// <summary>
/// Gets or sets the parameters parameter
Copy link
Contributor

Choose a reason for hiding this comment

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

:)


/// <summary>
/// Creates a policy assignment.
/// </summary>
[Cmdlet(VerbsCommon.New, "AzureRmPolicyAssignment"), OutputType(typeof(PSObject))]
public class NewAzurePolicyAssignmentCmdlet : PolicyAssignmentCmdletBase
public class NewAzurePolicyAssignmentCmdlet : PolicyAssignmentCmdletBase, IDynamicParameters
Copy link
Contributor

Choose a reason for hiding this comment

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

No api-version change for policy cmdlets?

@cormacpayne
Copy link
Member

@luanshixia the build is failing since you are introducing parameters PolicyParameters and Parameters, which do not follow the PowerShell convention of parameters having a singular noun

@@ -63,7 +63,7 @@ public static class Constants
/// <summary>
/// The default policy API version.
/// </summary>
public static readonly string PolicyApiVersion = "2016-04-01";
public static readonly string PolicyApiVersion = "2016-12-01";
Copy link
Contributor

Choose a reason for hiding this comment

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

just curious as to why the new API version date is set to December instead of a more recent date?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Per the resource schema seen on Azure Portal, the latest version for policy is 2016-12-01:

        {
            "resourceType": "policyDefinitions",
            "locations": [],
            "apiVersions": [
                "2016-12-01",
                "2016-04-01",
                "2015-10-01-preview"
            ]
        },
        {
            "resourceType": "policyAssignments",
            "locations": [],
            "apiVersions": [
                "2016-12-01",
                "2016-04-01",
                "2015-10-01-preview"
            ]
        },

/// The parameter values.
/// </summary>
[JsonProperty(Required = Required.Default)]
public JObject Parameters { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

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

You can rename this to Parameter to be consistent with the PolicyDefinitionProperties class

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately this property cannot be renamed because that should match the REST API. (I also only realized this when I caught an error after trying to keep consistency). Of course we can match names using JsonProperty attribute, but no need.

@luanshixia
Copy link
Contributor Author

@cormacpayne Thanks so much for the help. I will rollback my workaround once you have a fix.

parameterObject.Add(paramKey, valueObject);
}
return parameterObject;
}
}
}
Copy link
Contributor

@maphad maphad Feb 13, 2017

Choose a reason for hiding this comment

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

Add a newline at end of file.

keys = dict.Keys;
}
var parameterObject = new JObject();
foreach (string paramKey in keys)
Copy link
Contributor

Choose a reason for hiding this comment

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

you can use var instead of string as is the convention.

Copy link
Contributor Author

@luanshixia luanshixia Feb 13, 2017

Choose a reason for hiding this comment

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

Here "keys" is of type IEnumerable not IEnumerable<string> so paramKey will not be inferred as string unless declared specific.

/// <param name="dict">The <see cref="IDictionary"/> object.</param>
/// <param name="keys">The key set to extract from the <see cref="IDictionary"/> object. Default is all keys.</param>
/// <returns>The conversion result.</returns>
public static JObject ToParameterObject(this IDictionary dict, IEnumerable keys = null)
Copy link
Contributor

Choose a reason for hiding this comment

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

The method name ToParameterObject is specific to its use in the policy commandlet.
Since this is a utility method it can be used from elsewhere. Can we use a more generic name like ToJsonObject or ToJObject?

@@ -50,10 +61,31 @@ public class NewAzurePolicyAssignmentCmdlet : PolicyAssignmentCmdletBase
/// <summary>
/// Gets or sets the policy assignment policy definition parameter.
/// </summary>
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The pollicy definition object.")]
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The policy definition object.")]
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this line 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.

So @cormacpayne is working on a fix for BreakingChangeAnalyzer which prevents this PR from passing the build (the reason: the analyzer compares the parameter set with the previous build. In previous build this property belongs to the default parameter set, so it enforces this for later builds). This line is a workaround which can be removed after his fix.

}

return null;
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Add newline at end of file.

@@ -113,7 +120,8 @@ private JToken GetResource()
{
Description = this.Description ?? null,
DisplayName = this.DisplayName ?? null,
PolicyRule = JObject.Parse(GetPolicyRuleObject().ToString())
PolicyRule = JObject.Parse(GetPolicyRuleObject().ToString()),
Parameters = this.Parameter == null ? null : JObject.Parse(GetParametersObject().ToString())
Copy link
Contributor

Choose a reason for hiding this comment

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

scope local method calls as this.GetParametersObject()

Copy link
Contributor

@vivsriaus vivsriaus left a comment

Choose a reason for hiding this comment

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

LGTM

@luanshixia
Copy link
Contributor Author

@cormacpayne I have already got two peer approvals but I don't have the permission to merge it. Could you please merge it so that it can make the 2/15 deadline? Thanks!

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.

@luanshixia a couple of comments

@@ -50,10 +61,31 @@ public class NewAzurePolicyAssignmentCmdlet : PolicyAssignmentCmdletBase
/// <summary>
/// Gets or sets the policy assignment policy definition parameter.
/// </summary>
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The pollicy definition object.")]
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The policy definition object.")]
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia if this parameter is required in every single parameter set, why make this change? Previously it was a globally required parameter, so it was required in any parameter set you used. The same applies now with the changes you are trying to make here.

Copy link
Contributor Author

@luanshixia luanshixia Feb 15, 2017

Choose a reason for hiding this comment

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

@cormacpayne So there are 3 usages:

  • PolicyDefinition only
  • PolicyDefinition + PolicyParameterObject
  • PolicyDefinition + PolicyParameter

We don't want users to set both PolicyParameterObject and PolicyParameter, so we use two different sets for them. But we also need to allow users to set none of PolicyParameterObject and PolicyParameter, which comes the third set. Note we have to set Mandatory=true for PolicyParameterObject and PolicyParameter or we will get parameter set resolving conflict.

Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia I am fine with the three different parameter sets, but there is no need to change PolicyDefinition from a global parameter to a parameter that's in each of the three parameter sets (that is what is implied by being a global parameter).


protected const string PolicyParameterObjectParameterSetName = "Policy assignment with parameters via policy parameter object";
protected const string PolicyParameterStringParameterSetName = "Policy assignment with parameters via policy parameter string";
protected const string ParameterlessPolicyParameterSetName = "Policy assignment without parameters";
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia the name of this parameter set is misleading - Name and Scope (and PolicyDefinition based on its implementation) parameters are globally required parameters, so you are always going to need to provide a value for them, meaning you'll never have a parameter set that is "parameterless"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cormacpayne No, "parameter" here refers to the policy parameters, not the cmdlet parameters.. This is similar to what is done for template parameters in NewAzureRmResourceGroupDeployment.

}
};

return policyassignmentObject.ToJToken();
}

object IDynamicParameters.GetDynamicParameters()
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia why do you need to add dynamic parameters to this cmdlet? We try to avoid using them as much as possible since they cannot be picked up by our StaticAnalysis tooling and don't allow us to easily check any public interface changes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cormacpayne Because we want to allow users to specify the policy parameters through cmdlet parameters, so we have to dynamically parse the policy definition and extract a list of defined parameters. That is from the requirements. In the future, we also want to add IntelliSense for the dynamic parameters, just like what we did for template deployment.

@@ -175,6 +190,32 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -PolicyParameter
The policy parameter file path or policy parameter string.```yaml
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia please move "```yaml" to a new line since it is causing errors with the displayed markdown

```

### -PolicyParameterObject
The policy parameter object.```yaml
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia same comment

@@ -171,6 +171,19 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -Parameter
The parameters declaration for policy definition. This can either be a path to a file name containing the parameters declaration, or the parameters declaration as string.```yaml
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia same comment

@cormacpayne cormacpayne self-assigned this Feb 14, 2017
@cormacpayne
Copy link
Member

@vivsriaus can you approve the review you have started? You commented with LGTM, but it still says you have changes requested.

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.

@luanshixia a couple of more comments after talking with @markcowl

var dp = new RuntimeDefinedParameter
{
Name = param.Name,
ParameterType = typeString.Equals("array", StringComparison.OrdinalIgnoreCase) ? typeof(object[]) : typeof(string)
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia can you leverage typeString to include a switch case for types you would want to define (e.g., int, bool, etc.)? It seems like a bad idea to have the default type of non-arrays as string

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cormacpayne Per Policy doc, "the type of a parameter can be either string or array".

dp.Attributes.Add(new ParameterAttribute
{
Mandatory = false,
ValueFromPipelineByPropertyName = true,
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia what kind of scenario would lend users to use the ValueFromPipelineByPropertyName for these dynamic parameters?

Copy link
Contributor Author

@luanshixia luanshixia Feb 15, 2017

Choose a reason for hiding this comment

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

@cormacpayne Similarly, the user can put dynamic parameters in an object (say $param) and say: $param | New-AzureRmPolicyAssignment

{
Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = param.Name
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia this is not good help for users, it's just repeating the parameter name

Name = param.Name,
ParameterType = typeString.Equals("array", StringComparison.OrdinalIgnoreCase) ? typeof(object[]) : typeof(string)
};
dp.Attributes.Add(new ParameterAttribute
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia the dynamic parameters will need to be in the Parameterless parameter set, or else users will be able to use them with the provided hashtable or json, which will defeat the purpose of having the dynamic parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cormacpayne Good catch.

[Parameter(ParameterSetName = PolicyParameterObjectParameterSetName,
Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The policy definition object.")]
[Parameter(ParameterSetName = PolicyParameterStringParameterSetName,
Mandatory = true, ValueFromPipelineByPropertyName = true, HelpMessage = "The policy definition object.")]
Copy link
Member

Choose a reason for hiding this comment

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

@luanshixia how will users use this ValueFromPipelineByPropertyName attribute for this parameter? Will there be an object they can pass through the pipeline to this cmdlet that contains the PolicyDefinition property? Will it also include the below parameters you are trying to add since they also have the ValueFromPipelineByPropertyName attribute as well?

Copy link
Contributor Author

@luanshixia luanshixia Feb 15, 2017

Choose a reason for hiding this comment

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

@cormacpayne I checked the existing code and found pipeline usage is supported across all Resources cmdlets. So the user can do like: @{"PolicyDefinition": @{...} ...} | New-AzureRmPolicyAssignment

@cormacpayne
Copy link
Member

@cormacpayne
Copy link
Member

LGTM once on-demand passes

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.

6 participants