Below is description of the various types of Breaking Change Attributes (custom attributes) that can be used to decorate the cmdlet or its paramters to call out various types of breaking changes.
- Common stuff and The generic breaking change attribute
- Cmdlet deprecation attribute
- Cmdlet output breaking change attribute
- Cmdlet parameter properties change attribute
The base attibute which provides the core functionality is called "GenericBreakingChange" All the remaining attrbutes derive from it and provide functionality that makes sense for the scenarios they handle.
The generic attribute is the most free form of them all and can be used to call out breaking changes that do not fall into the more specialized categories.
All of the attributes have the following common traits:
- The attribute (when added to the cmdlet/parameter of the cmdlet) is used for the following purposes
- At runtime, if the cmdlet is used, we will print out a message for each breaking change attribute present in the cmdlet and its properties.
- We use these attributes to generate the breaking change document for the cmdlet.
- Each attribute has two additional constructors thet take the following params in addition to the ones the attribute mentions:
- The "deprecatedByVersion" is the version number the breaking change is going to be done in.
- The "changeInEfectByDate" is the date the breaking change is goind to go in effet on. The string formati is "mm/dd/yyyy", as an example : "02/25/2018"
- Each attribute accepts the following properties by name (all of them are optional) :
- "ChangeDescription" : This is a free form text field that can be used to describe the breaking change.
- Usage changes (you cant have one or the other, you need to speciffy both for the usage message to be generated) :
- "OldWay" : The way to call the cmdlet before the breaking change takes effect
- "NewWay" : If there is a workaround to the breaking change, or if the same functionality can be achieved in another manner
The properties "deprecatedByVersion" and "changeInEfectByDate" are infotmation only (for the end user) as of now.
- If the user desires to not see the warning messages generated by the attirbutes at runtime, they can set the env variable "SuppressAzurePowerShellBreakingChangeWarnings" to "true".
NOTE :
- The only time you will see the output (at runtime) of an attribute applied to a parameter (property or field) is if the parameter is actually invoked on the cmdline. The breaking change attributes to all parameters that are not invoked are ignored.
[GenericBreakingChange("Message 1")]
[Cmdlet(VerbsCommon.Get, "SomeObject0"), OutputType(typeof(Foo))]
class GetSomeObject0 : AzureRMCmdlet
{
}
Get-SomeObject0 <parms here>
...
Breaking changes in the cmdlet : Get-SomeObject0
- Message 1
[GenericBreakingChange("Message 1", "5.0.0.0")]
[Cmdlet(VerbsCommon.Get, "SomeObjectA"), OutputType(typeof(Foo))]
class GetSomeObjectA : AzureRMCmdlet
{
}
Get-SomeObjectA <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectA
- Message 1
The change is expected to take effect from the version : 5.0.0.0
[GenericBreakingChange("Message2", "5.0.0.0", "02/13/2018")]
[Cmdlet(VerbsCommon.Get, "SomeObjectB"), OutputType(typeof(Foo))]
class GetSomeObjectB : AzureRMCmdlet
}
Get-SomeObjectB <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectB
- Message 2
NOTE : This change will take effect on '02/13/2018'
The change is expected to take effect from the version : 5.0.0.0
[GenericBreakingChange("Added new required param to Get-SomeObjectC", OldWay = "Get-SomeObjectC -Param1=\"blah\"", NewWay = "Get-SomeObjectC -Param1=\"blah\" -Param2=\"Yo Yo\"")]
[Cmdlet(VerbsCommon.Get, "SomeObjectC"), OutputType(typeof(Foo))]
class GetSomeObjectC : AzureRMCmdlet
}
Get-SomeObjectC <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectC
- Added new required param to Get-SomeObjectC
Cmdlet invocation changes :
Old Way : Get-SomeObjectC -Param1="blah"
New Way : Get-SomeObjectC -Param1="blah" -Param2="Yo Yo"
[GenericBreakingChange("Message5")]
[Cmdlet(VerbsCommon.Get, "SomeObjectD"), OutputType(typeof(Foo))]
class GetSomeObjectD : AzureRMCmdlet
//This is just as an example, to call out a param change we would not use the generic attribute. Use "CmdletParameterBreakingChangeMarker" instead
[GenericBreakingChange("Param1 changes coming", ChangeDescription = "The param is changing from a List<String> to HashSet<String>")]
[Parameter(Mandatory = false)]
public List<String> Param1;
[Parameter(Mandatory = false)]
public List<String> Param2;
}
Get-SomeObjectC -Param1=...
...
Breaking changes in the cmdlet : Get-SomeObjectD
- Message5
- Param1 changes coming
Change description : The param is changing from a List<String> to HashSet<String>"
Get-SomeObjectC -Param2=...
...
Breaking changes in the cmdlet : Get-SomeObjectD
- Message5
This attribute marks a cmdlet for deprecation.
None, other than the two inherited from GenericBreakingChangeAttribute
[CmdletDeprecation(ReplacementCmdletName = "Get-SomeObjectC")]
[Cmdlet(VerbsCommon.Get, "SomeObjectA"), OutputType(typeof(Foo))]
public class GetSomeObjectA : AzureRMCmdlet
{
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectA <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectA
The cmdlet 'Get-SomeObjectC' is replacing this cmdlet
[CmdletDeprecation()]
[Cmdlet(VerbsCommon.Get, "SomeObjectB"), OutputType(typeof(Foo))]
public class GetSomeObjectB : AzureRMCmdlet
{
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectB <params here>
...
Breaking changes in the cmdlet : Get-SomeObjectB
The cmdlet is being deprecated. There will be no replacement for it.
This attribute is used to call out the breakigng changes with the output of a cmdlet. A few examples are :
- The type of the output is changing
- The Output type is being deprecated
- Some internal properties in the putput type are being deprecated
- New properties are being introduced to the output type
Note :
- It is possible to mix the above, as in you can have a case where a type is being replaced and we want to call out the change to internal properties, as in list te old ones deprecating with the old type and the new ones being introduced in the new type
- deprecatedCmdletOutputTypeName : String, represents the type of the existing output type,
- The two inherited from GenericBreakingChangeAttribute
[CmdletOutputBreakingChange(typeof(Foo))]
[Cmdlet(VerbsCommon.Get, "SomeObjectA"), OutputType(typeof(Foo))]
public class GetSomeObjectA : AzureRMCmdlet
{
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectA <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectA
- The output type 'Foo' is being deprecated without a replacement.
[CmdletOutputBreakingChange(typeof(Foo), ReplacementCmdletOutputTypeName = "Dictionary<String, Foo>")]
[Cmdlet(VerbsCommon.Get, "SomeObjectA"), OutputType(typeof(Foo))]
public class GetSomeObjectA : AzureRMCmdlet
{
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectA <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectA
- The output type is changing from the existing type :'List<Foo>' to the new type :'Dictionary<String, Foo>'
[CmdletOutputBreakingChange(typeof(Foo), DeprecatedOutputProperties = new String[] {"Prop1", "Prop2"})]
[Cmdlet(VerbsCommon.Get, "SomeObjectB"), OutputType(typeof(Foo))]
public class GetSomeObjectB : AzureRMCmdlet
{
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectB <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectB
- The output type 'Foo' is changing
- The following properties in the output type are being deprecated :
'Prop1' 'Prop2'
[CmdletOutputBreakingChange(typeof(Foo), NewOutputProperties = new String[] {"Prop1", "Prop2"})]
[Cmdlet(VerbsCommon.Get, "SomeObjectC"), OutputType(typeof(Foo))]
public class GetSomeObjectC : AzureRMCmdlet
{
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectC <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectC
- The output type 'Foo' is changing
- The following properties are being added to the output type :
'Prop1' 'Prop2'
[CmdletOutputBreakingChange(typeof(Foo), ReplacementCmdletOutputTypeName = "Foo1",
DeprecatedOutputProperties = new String[] {"Prop1", "Prop2"},
NewOutputProperties = new String[] {"Prop3", "Prop4"})]
[Cmdlet(VerbsCommon.Get, "SomeObjectD"), OutputType(typeof(Foo))]
public class GetSomeObjectD : AzureRMCmdlet
{
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectD <parms here>
...
Breaking changes in the cmdlet : Get-SomeObjectD
- The output type is changing from the existing type :'Foo' to the new type :'Foo1'
- The following properties in the output type are being deprecated :
'Prop1' 'Prop2'
- The following properties are being added to the output type :
'Prop3' 'Prop4'
This attribute is used to call out the breakigng changes relating to a parameter of a cmdlet. A few examples are :
- A parameter is being deprecated
- A parameter is being replaced
- A parameter is becoming mandatory
- A non mandatory parameter is being replaced by a mandatory parameter
NOTE :
- The only time you will see the output (at runtime) of an attribute applied to a parameter (property or field) is if the parameter is actually invoked on the cmdline. The breaking change attributes to all parameters that are not invoked are ignored.
- nameOfParameterChanging : String, represents the name of the existing parameter,
- The two inherited from GenericBreakingChangeAttribute
[Cmdlet(VerbsCommon.Get, "SomeObjectA0"), OutputType(typeof(Foo))]
public class GetSomeObjectA0 : AzureRMCmdlet
{
public const String ChangeDesc = "Change description Foo bar";
[CmdletParameterBreakingChange("Param1", ChangeDescription = ChangeDesc)]
[Parameter(Mandatory = false)]
public String Param1;
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectA0 -Param1=...
...
Breaking changes in the cmdlet : Get-SomeObjectA0
- The parameter 'Param1' is changing
Change description : Change description Foo bar
[Cmdlet(VerbsCommon.Get, "SomeObjectA"), OutputType(typeof(Foo))]
public class GetSomeObjectA : AzureRMCmdlet
{
public const String ChangeDesc = "Parameter is being deprecated without being replaced";
[CmdletParameterBreakingChange("Param1", ChangeDescription = ChangeDesc)]
[Parameter(Mandatory = false)]
public String Param1;
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectA -Param1=...
...
Breaking changes in the cmdlet : Get-SomeObjectA
- The parameter 'Param1' is changing
Change description : Parameter is being deprecated without being replaced
[Cmdlet(VerbsCommon.Get, "SomeObjectA1"), OutputType(typeof(Foo))]
public class GetSomeObjectA1 : AzureRMCmdlet
{
[CmdletParameterBreakingChange("Param1", OldParameterType = typeof(String), NewParameterTypeName="FooBar")]
[Parameter(Mandatory = false)]
public String Param1;
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectA1 -Param1=...
...
Breaking changes in the cmdlet : Get-SomeObjectA1
- The parameter 'Param1' is changing
The type of the parameter is changing from 'String' to 'FooBar'.
[Cmdlet(VerbsCommon.Get, "SomeObjectB"), OutputType(typeof(Foo))]
public class GetSomeObjectB : AzureRMCmdlet
{
[CmdletParameterBreakingChange("Param1", ReplaceMentCmdletParameterName = "ParamX")]
[Parameter(Mandatory = false)]
public String Param1;
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectB -Param1=...
...
Breaking changes in the cmdlet : Get-SomeObjectB
- The parameter 'Param1' is being replaced by parameter "ParamX"
[Cmdlet(VerbsCommon.Get, "SomeObjectC"), OutputType(typeof(Foo))]
public class GetSomeObjectC : AzureRMCmdlet
{
[CmdletParameterBreakingChange("Param1", ReplaceMentCmdletParameterName = "ParamX",
IsBecomingMandatory=true)]
[Parameter(Mandatory = false)]
public String Param1;
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectC -Param1=...
...
Breaking changes in the cmdlet : Get-SomeObjectB
- The parameter 'Param1' is being replaced by mandatory parameter "ParamX"
[Cmdlet(VerbsCommon.Get, "SomeObjectA"), OutputType(typeof(Foo))]
public class GetSomeObjectA : AzureRMCmdlet
{
[CmdletParameterBreakingChange("Param1", IsBecomingMandatory=truec)]
[Parameter(Mandatory = false)]
public String Param1;
protected override void BeginProcessing()
{
// cmdlet logic
}
}
Get-SomeObjectA -Param1=...
...
Breaking changes in the cmdlet : Get-SomeObjectA
- The parameter 'Param1' is becoming mandatory