From 22cb155b78f460d1c62fe7756041d4716212c033 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 26 May 2022 13:53:47 +0800 Subject: [PATCH 01/16] Create using-config-framework.md --- .../development-docs/using-config-framework.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 documentation/development-docs/using-config-framework.md diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md new file mode 100644 index 000000000000..7545339fd608 --- /dev/null +++ b/documentation/development-docs/using-config-framework.md @@ -0,0 +1,15 @@ +# Using Config Framework + +## Overview + +## Guide: How to Add a New Config + +## Guide: How to Get the Value of a Config + +## Special cases + +### Applies to + +### Validation + +### Environment variable From 94bae5e9811def9b6741bf9ccf9fdeb5dd539996 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Fri, 27 May 2022 09:30:24 +0800 Subject: [PATCH 02/16] Update using-config-framework.md --- .../using-config-framework.md | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 7545339fd608..a701237b33a0 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -1,15 +1,38 @@ # Using Config Framework +- [Overview](#overview) +- [Guide: How to Add a New Config](#guide-how-to-add-a-new-config) +- [Guide: How to Get the Value of a Config](#guide-how-to-get-the-value-of-a-config) +- [Special cases](#special-cases) + - [Applies to](#applies-to) + - [Validation](#validation) + - [Environment variable](#environment-variable) + ## Overview +The config framework was introduced in Az 8, May 2022 to set up a standard of how to define a config, get or update the value of a config, etc. + +This document will go over 2 most common scenarios for developers. + ## Guide: How to Add a New Config +### Step 1: Define the Config + +To define a config, add a new class inheriting `TypedConfig` under src/Accounts/Authentication/Config/Definitions/ + +Simple config +Customized config + +### Step 2: Register the Config + +### Step 3: Regenerate Help Documents + ## Guide: How to Get the Value of a Config -## Special cases +## Special Cases ### Applies to ### Validation -### Environment variable +### Environment Variable From 32816f4a3c0c37eba2c7aaba77308d06e10fc0de Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Fri, 27 May 2022 15:17:06 +0800 Subject: [PATCH 03/16] Update using-config-framework.md --- documentation/development-docs/using-config-framework.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index a701237b33a0..7e23f61e4c4c 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -10,15 +10,17 @@ ## Overview -The config framework was introduced in Az 8, May 2022 to set up a standard of how to define a config, get or update the value of a config, etc. +The config framework was introduced in Az 8, May 2022 to set up a standard of how configs are used by both developers and end users of Azure PowerShell. -This document will go over 2 most common scenarios for developers. +This document will go over 2 most common scenarios for developers. As for how to set configs please refer to [Update-AzConfig](https://docs.microsoft.com/powershell/module/az.accounts/update-azconfig). ## Guide: How to Add a New Config ### Step 1: Define the Config -To define a config, add a new class inheriting `TypedConfig` under src/Accounts/Authentication/Config/Definitions/ +To define a config, create a class inheriting [`TypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/TypedConfig.cs) and place it at [`src/Accounts/Authentication/Config/Definitions/`](https://github.com/Azure/azure-powershell/tree/main/src/Accounts/Authentication/Config/Definitions), where you can also find examples of other configs. + +You will find Simple config Customized config From 59d3f3fe16581bfdad0bf972f89935862a94bd43 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:00:19 +0800 Subject: [PATCH 04/16] Update using-config-framework.md --- .../using-config-framework.md | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 7e23f61e4c4c..e05329daf574 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -18,12 +18,25 @@ This document will go over 2 most common scenarios for developers. As for how to ### Step 1: Define the Config -To define a config, create a class inheriting [`TypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/TypedConfig.cs) and place it at [`src/Accounts/Authentication/Config/Definitions/`](https://github.com/Azure/azure-powershell/tree/main/src/Accounts/Authentication/Config/Definitions), where you can also find examples of other configs. +#### Standard Config Definition -You will find +To define a config, create a class inheriting [`TypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/TypedConfig.cs) and place it at [`src/Accounts/Authentication/Config/Definitions/`](https://github.com/Azure/azure-powershell/tree/main/src/Accounts/Authentication/Config/Definitions), where you can also find other examples of configs. -Simple config -Customized config +You will need to override the following key properties when defining your own config class. + +- `object DefaultValue` + - The default value of the config. +- `string Key` + - The unique key of the config. + - The key is also used as a parameter name of cmdlets that operate on configs, for example `Get-AzConfig`, so it must follow the naming conventions. See [Parameter Best Practices](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/design-guidelines/parameter-best-practices.md#parameter-best-practices). +- `string HelpMessage` + - The help message or description of the config. + - It will also be used as the help message of the corresponding PowerShell parameter in documents. + +public override string EnvironmentVariableName => "AZURE_PS_DISPLAY_BREAKING_CHANGE_WARNINGS"; +``` + +#### Simple Config Definition ### Step 2: Register the Config @@ -33,8 +46,16 @@ Customized config ## Special Cases -### Applies to +### Limit the Possibility of AppliesTo + +### Validation of Config Value + +### Environment Variables + + -### Validation +- (optional) `string EnvironmentVariableName` + - If the config can also be set by an environment variable, and the value of the environment variable can be parsed as the value type `TValue`, override this property. + - For more complicated scenarios of using environment variables, such as you need to customize the logic of parsing it, do not use this property. See [todo] below. -### Environment Variable +### Use From c1f12f286f4fd15eedf5019a204ea96dbf6a7e66 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Wed, 1 Jun 2022 21:30:48 +0800 Subject: [PATCH 05/16] Update using-config-framework.md --- .../using-config-framework.md | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index e05329daf574..607ffc16ce36 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -25,19 +25,24 @@ To define a config, create a class inheriting [`TypedConfig`](https://gi You will need to override the following key properties when defining your own config class. - `object DefaultValue` - - The default value of the config. + - The default value of the config. Used for basic type validation when setting the config. - `string Key` - - The unique key of the config. - - The key is also used as a parameter name of cmdlets that operate on configs, for example `Get-AzConfig`, so it must follow the naming conventions. See [Parameter Best Practices](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/design-guidelines/parameter-best-practices.md#parameter-best-practices). + - The unique key of the config. Used when user gets or sets the config. + - The key is reused as a parameter name of cmdlets that operate on configs, for example `Get-AzConfig`, so it must follow the naming conventions. See [Parameter Best Practices](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/design-guidelines/parameter-best-practices.md#parameter-best-practices). - `string HelpMessage` - - The help message or description of the config. - - It will also be used as the help message of the corresponding PowerShell parameter in documents. - -public override string EnvironmentVariableName => "AZURE_PS_DISPLAY_BREAKING_CHANGE_WARNINGS"; -``` + - The help message or description of the config. + - It is reused as the help message of the corresponding PowerShell parameter in documents. #### Simple Config Definition +If the following circumstances are met, you may simpify the code by creating an instance of [`SimpleTypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/SimpleTypedConfig.cs) instead of defining your own type: +- The config does not support environment variables. Or it supports only one environment variable and it does not require special logic to parse the value. +- No special validation logic. + + + + + ### Step 2: Register the Config ### Step 3: Regenerate Help Documents From 35b506bea882e8166d81e59212f4f8e897cb2981 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 2 Jun 2022 09:59:33 +0800 Subject: [PATCH 06/16] Update using-config-framework.md --- documentation/development-docs/using-config-framework.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 607ffc16ce36..2c0ddf50904b 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -35,8 +35,10 @@ You will need to override the following key properties when defining your own co #### Simple Config Definition +To reduce scaffolding, [`SimpleTypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/SimpleTypedConfig.cs) was introduced + If the following circumstances are met, you may simpify the code by creating an instance of [`SimpleTypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/SimpleTypedConfig.cs) instead of defining your own type: -- The config does not support environment variables. Or it supports only one environment variable and it does not require special logic to parse the value. +- The config does not support environment variables, or it is connected to **one single** environment variable and it does not require special logic to parse the value. - No special validation logic. From e1558ec99c4c3d55c5ebadb6385a49c6bd8c44d9 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 2 Jun 2022 13:08:11 +0800 Subject: [PATCH 07/16] Update using-config-framework.md --- .../using-config-framework.md | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 2c0ddf50904b..21b2701b081f 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -18,6 +18,36 @@ This document will go over 2 most common scenarios for developers. As for how to ### Step 1: Define the Config +#### Simple Config Definition + +For most cases, creating an instance of [`SimpleTypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/SimpleTypedConfig.cs) is the easist way to define a config. The syntax is: + +```csharp +SimpleTypedConfig.SimpleTypedConfig(string key, string helpMessage, TValue defaultValue, [string environmentVariable = null], [IReadOnlyCollection canApplyTo = null]) +``` +where +- `TValue` is the type of the value of the config, for example `int` or `bool`. +- `key` is the unique key of the config. It is used when user gets or sets the config. + - It must be defined in [src/shared/ConfigKeys.cs](https://github.com/Azure/azure-powershell/blob/main/src/shared/ConfigKeys.cs) so that it can be referenced in any project. + - It is reused as a parameter name of cmdlets that operate on configs, for example `Get-AzConfig`, so it must follow the naming conventions. See [Parameter Best Practices](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/design-guidelines/parameter-best-practices.md#parameter-best-practices). +- `helpMessage` is the help message or description of the config. + - It is reused as the help message of the corresponding PowerShell parameter in documents. +- `defaultValue` is the default value of the config. Used for basic type validation when setting the config. +- (Optional) `environmentVariable` sets to which environment variable the config is connected. Once set, the config framework will pick up the variable automatically. + - Note: the config must correspond to **one single** environment variable and it must not require special logic to parse the value. Otherwise please check out [todo]. +- (Optional) `canApplyTo` + +A sample definition: + +```csharp +new SimpleTypedConfig( + ConfigKeys.DefaultSubscriptionForLogin, + Resources.HelpMessageOfDefaultSubscriptionForLogin, + string.Empty, + "AZURE_ENV_VAR_FOR_SUBSCRIPTION", + new[] { AppliesTo.Az }); +``` + #### Standard Config Definition To define a config, create a class inheriting [`TypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/TypedConfig.cs) and place it at [`src/Accounts/Authentication/Config/Definitions/`](https://github.com/Azure/azure-powershell/tree/main/src/Accounts/Authentication/Config/Definitions), where you can also find other examples of configs. @@ -33,13 +63,6 @@ You will need to override the following key properties when defining your own co - The help message or description of the config. - It is reused as the help message of the corresponding PowerShell parameter in documents. -#### Simple Config Definition - -To reduce scaffolding, [`SimpleTypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/SimpleTypedConfig.cs) was introduced - -If the following circumstances are met, you may simpify the code by creating an instance of [`SimpleTypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/SimpleTypedConfig.cs) instead of defining your own type: -- The config does not support environment variables, or it is connected to **one single** environment variable and it does not require special logic to parse the value. -- No special validation logic. From 008cfc78e402c280e364acb2984034815355f221 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 2 Jun 2022 13:28:18 +0800 Subject: [PATCH 08/16] Update using-config-framework.md --- .../using-config-framework.md | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 21b2701b081f..bdae8480f277 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -35,9 +35,9 @@ where - `defaultValue` is the default value of the config. Used for basic type validation when setting the config. - (Optional) `environmentVariable` sets to which environment variable the config is connected. Once set, the config framework will pick up the variable automatically. - Note: the config must correspond to **one single** environment variable and it must not require special logic to parse the value. Otherwise please check out [todo]. -- (Optional) `canApplyTo` +- (Optional) `canApplyTo` defines at which levels the config can apply to. There are three levels in total: `AppliesTo.Az`, `AppliesTo.Module`, `AppliesTo.Cmdlet`. By default all of them are included. For more details, see [todo]. -A sample definition: +Here is a sample definition: ```csharp new SimpleTypedConfig( @@ -50,28 +50,35 @@ new SimpleTypedConfig( #### Standard Config Definition -To define a config, create a class inheriting [`TypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/TypedConfig.cs) and place it at [`src/Accounts/Authentication/Config/Definitions/`](https://github.com/Azure/azure-powershell/tree/main/src/Accounts/Authentication/Config/Definitions), where you can also find other examples of configs. +The more standard way to define a config is to create a class inheriting [`TypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/TypedConfig.cs). It should be placed at [`src/Accounts/Authentication/Config/Definitions/`](https://github.com/Azure/azure-powershell/tree/main/src/Accounts/Authentication/Config/Definitions), where you can also find other examples of configs. -You will need to override the following key properties when defining your own config class. +Like simple definition, you will need to override some key properties, which will not be repeated here. -- `object DefaultValue` - - The default value of the config. Used for basic type validation when setting the config. -- `string Key` - - The unique key of the config. Used when user gets or sets the config. - - The key is reused as a parameter name of cmdlets that operate on configs, for example `Get-AzConfig`, so it must follow the naming conventions. See [Parameter Best Practices](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/design-guidelines/parameter-best-practices.md#parameter-best-practices). -- `string HelpMessage` - - The help message or description of the config. - - It is reused as the help message of the corresponding PowerShell parameter in documents. +Here is a sample definition: +```csharp +internal class DisplayBreakingChangeWarningsConfig : TypedConfig +{ + public override object DefaultValue => true; + public override string Key => ConfigKeys.DisplayBreakingChangeWarning; + public override string HelpMessage => Resources.HelpMessageOfDisplayBreakingChangeWarnings; +} +``` +### Step 2: Register the Config +Either way the config is defined, instanciate it and call [`IConfigManager.RegisterConfig(ConfigDefinition config)`](https://github.com/Azure/azure-powershell-common/blob/8d70507d41a3698b5b131df61f14e329d7a6eb41/src/Authentication.Abstractions/Interfaces/IConfigManager.cs#L30) in [`ConfigInitializer.RegisterConfigs(IConfigManager configManager)`](https://github.com/Azure/azure-powershell/blob/304e15c84071fee02622734c4e5f12c05baa77d2/src/Accounts/Authentication/Config/ConfigInitializer.cs#L192). For example: -### Step 2: Register the Config +```csharp +configManager.RegisterConfig(new DisplayBreakingChangeWarningsConfig()); +``` ### Step 3: Regenerate Help Documents +As mentioned in Step 1, the key + ## Guide: How to Get the Value of a Config ## Special Cases From fc10739761e536c0108b7de1c29ae76ad6764d68 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 2 Jun 2022 13:54:59 +0800 Subject: [PATCH 09/16] Update using-config-framework.md --- documentation/development-docs/using-config-framework.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index bdae8480f277..87951773b934 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -67,6 +67,8 @@ internal class DisplayBreakingChangeWarningsConfig : TypedConfig } ``` +Definining configs in the standard way is more customizable than the simple way, for example when it comes to validating values and parsing enviroment variables. For more, see [todo]. + ### Step 2: Register the Config Either way the config is defined, instanciate it and call [`IConfigManager.RegisterConfig(ConfigDefinition config)`](https://github.com/Azure/azure-powershell-common/blob/8d70507d41a3698b5b131df61f14e329d7a6eb41/src/Authentication.Abstractions/Interfaces/IConfigManager.cs#L30) in [`ConfigInitializer.RegisterConfigs(IConfigManager configManager)`](https://github.com/Azure/azure-powershell/blob/304e15c84071fee02622734c4e5f12c05baa77d2/src/Accounts/Authentication/Config/ConfigInitializer.cs#L192). For example: @@ -75,9 +77,11 @@ Either way the config is defined, instanciate it and call [`IConfigManager.Regis configManager.RegisterConfig(new DisplayBreakingChangeWarningsConfig()); ``` +Up until now, you are able to test this new config with `Get-AzConfig`, `Update-AzConfig` and `Clear-AzConfig`. For more, run `Get-Help Get-AzConfig`. + ### Step 3: Regenerate Help Documents -As mentioned in Step 1, the key +As mentioned in Step 1, each config maps to a parameter of `Get-AzConfig`, `Update-AzConfig`, and `Clear-AzConfig`, so it is important to regenerate help documents after introducing new configs. Here are [the instructions](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/help-generation.md#updating-help-after-making-cmdlet-changes). ## Guide: How to Get the Value of a Config From 245b58f490d7857c7ed4b5b835c6af56d11cc883 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 2 Jun 2022 14:26:02 +0800 Subject: [PATCH 10/16] Update using-config-framework.md --- documentation/development-docs/using-config-framework.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 87951773b934..9f7f6ab403b9 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -85,6 +85,15 @@ As mentioned in Step 1, each config maps to a parameter of `Get-AzConfig`, `Upda ## Guide: How to Get the Value of a Config +Now that you have defined and registered the config, it is time to get its value. First you need to get the singleton of `IConfigManager`, then use `T GetConfigValue(string key, object invocation = null);`. For example: + +```csharp +AzureSession.Instance.TryGetComponent(nameof(IConfigManager), out var configManager); +string subscriptionFromConfig = configManager.GetConfigValue(ConfigKeys.DefaultSubscriptionForLogin, MyInvocation); +``` + +Note that although `invocation` is optional, if the config can apply to either `AppliesTo.Module` or `AppliesTo.Cmdlet` (see [todo]), it must be `MyInvocation`. + ## Special Cases ### Limit the Possibility of AppliesTo From 2909e9ab8be10723c552e9b6db1f47053128a054 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 2 Jun 2022 14:49:56 +0800 Subject: [PATCH 11/16] Update using-config-framework.md --- .../development-docs/using-config-framework.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 9f7f6ab403b9..8a2df65f3ea4 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -92,11 +92,18 @@ AzureSession.Instance.TryGetComponent(nameof(IConfigManager), ou string subscriptionFromConfig = configManager.GetConfigValue(ConfigKeys.DefaultSubscriptionForLogin, MyInvocation); ``` -Note that although `invocation` is optional, if the config can apply to either `AppliesTo.Module` or `AppliesTo.Cmdlet` (see [todo]), it must be `MyInvocation`. +Note that although `invocation` is optional, if the config can apply to either `AppliesTo.Module` or `AppliesTo.Cmdlet` (see [todo]), it must be `MyInvocation`. Alternatively, it could be a good idea to always pass in `MyInvocation`. -## Special Cases +## Lesser Topics + +### About AppliesTo + +Configs cannot only be set globally, but also be set for a certain cmdlet or module. For example, the following script disables breaking change warning messages for `Az.KeyVault` module. + +```powershell +Update-AzConfig -DisplayBreakingChangeWarning $false -AppliesTo Az.KeyVault +``` -### Limit the Possibility of AppliesTo ### Validation of Config Value From 91ebf63f614efcbced5a48beb90caa65045d9999 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Tue, 7 Jun 2022 13:39:33 +0800 Subject: [PATCH 12/16] Update using-config-framework.md --- documentation/development-docs/using-config-framework.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 8a2df65f3ea4..69a583cd547b 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -104,6 +104,9 @@ Configs cannot only be set globally, but also be set for a certain cmdlet or mod Update-AzConfig -DisplayBreakingChangeWarning $false -AppliesTo Az.KeyVault ``` +The `IReadOnlyCollection ConfigDefinition.CanApplyTo { get; }` property controls how a config can be applied.! + + ### Validation of Config Value From 731ea8ca738a86e145ba16a877193270c254a23c Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 9 Jun 2022 09:52:51 +0800 Subject: [PATCH 13/16] Update using-config-framework.md --- .../using-config-framework.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 69a583cd547b..542051f87a9d 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -98,17 +98,30 @@ Note that although `invocation` is optional, if the config can apply to either ` ### About AppliesTo -Configs cannot only be set globally, but also be set for a certain cmdlet or module. For example, the following script disables breaking change warning messages for `Az.KeyVault` module. +Configs cannot only be set globally, but also be set for a certain cmdlet or module. For example, the following script disables breaking change warning messages for `Az.KeyVault` module, while other modules are not affected by it. ```powershell Update-AzConfig -DisplayBreakingChangeWarning $false -AppliesTo Az.KeyVault ``` -The `IReadOnlyCollection ConfigDefinition.CanApplyTo { get; }` property controls how a config can be applied.! +The `IReadOnlyCollection ConfigDefinition.CanApplyTo { get; }` property controls to which levels a config can be applied. For example, if it does not make sense for your config to apply to a module or cmdlet, you should set the property to `new AppliesTo[] { AppliesTo.Az }`. +### Validation of Config Value +By default, when setting the value of a config, the type of the value is validated. If you want to implement your own validation, override `void TypedConfig.Validate(object value)`, throw an exception when the value is invalid. -### Validation of Config Value +```powershell +public override void Validate(object value) +{ + // do not forget to call `base` so type is still checked + base.Validate(value); + int valueInt = (int)value; + if (value < 0 || value > 100)) + { + throw new ArgumentException($"Unexpected value [{value}]. The value of config [{Key}] should be between 0 and 100.", nameof(value)); + } +} +``` ### Environment Variables From da2637cb446289508eb225c252402d6584ac9315 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 9 Jun 2022 10:28:28 +0800 Subject: [PATCH 14/16] Update using-config-framework.md --- .../using-config-framework.md | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 542051f87a9d..4e206de6cc1e 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -123,12 +123,32 @@ public override void Validate(object value) } ``` -### Environment Variables +### Parsing Environment Variables +Some configs can also be set via environment variables. The config framework will try to parse the variable by the key you set for `string EnvironmentVariableName` property. +However, if for any of the following situations, you need to implement your onw parsing logic: +- Multiple environment variables control one config. +- The value cannot be parsed directly. For example string "Y" to boolean "true". -- (optional) `string EnvironmentVariableName` - - If the config can also be set by an environment variable, and the value of the environment variable can be parsed as the value type `TValue`, override this property. - - For more complicated scenarios of using environment variables, such as you need to customize the logic of parsing it, do not use this property. See [todo] below. +In this case, instead of setting `EnvironmentVariableName`, override `string ParseFromEnvironmentVariables(IReadOnlyDictionary environmentVariables)`. For example: + +```csharp +// `environmentVariables` contains all the environment variables +public override string ParseFromEnvironmentVariables(IReadOnlyDictionary environmentVariables) +{ + if (environmentVariables.TryGetValue("Azure_PS_Intercept_Survey", out string configString)) + { + if ("Disabled".Equals(configString, StringComparison.OrdinalIgnoreCase) + || "False".Equals(configString, StringComparison.OrdinalIgnoreCase)) + { + // note the return type is string + return false.ToString(); + } + } + // returning null means the variable is not set + return null; +} +``` ### Use From e504c4d7309aee0eb14edb61bebcd9e3c6936f67 Mon Sep 17 00:00:00 2001 From: Yeming Liu <11371776+isra-fel@users.noreply.github.com> Date: Thu, 9 Jun 2022 10:32:45 +0800 Subject: [PATCH 15/16] Update using-config-framework.md --- .../using-config-framework.md | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 4e206de6cc1e..435de4c08367 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -2,11 +2,16 @@ - [Overview](#overview) - [Guide: How to Add a New Config](#guide-how-to-add-a-new-config) + - [Step 1: Define the Config](#step-1-define-the-config) + - [Simple Config Definition](#simple-config-definition) + - [Standard Config Definition](#standard-config-definition) + - [Step 2: Register the Config](#step-2-register-the-config) + - [Step 3: Regenerate Help Documents](#step-3-regenerate-help-documents) - [Guide: How to Get the Value of a Config](#guide-how-to-get-the-value-of-a-config) -- [Special cases](#special-cases) - - [Applies to](#applies-to) - - [Validation](#validation) - - [Environment variable](#environment-variable) +- [Customizing Config Definitions](#customizing-config-definitions) + - [About AppliesTo](#about-appliesto) + - [Validation of Config Value](#validation-of-config-value) + - [Parsing Environment Variables](#parsing-environment-variables) ## Overview @@ -20,7 +25,7 @@ This document will go over 2 most common scenarios for developers. As for how to #### Simple Config Definition -For most cases, creating an instance of [`SimpleTypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/SimpleTypedConfig.cs) is the easist way to define a config. The syntax is: +For most cases, creating an instance of [`SimpleTypedConfig`](https://github.com/Azure/azure-powershell/blob/main/src/Accounts/Authentication/Config/Models/SimpleTypedConfig.cs) is the easiest way to define a config. The syntax is: ```csharp SimpleTypedConfig.SimpleTypedConfig(string key, string helpMessage, TValue defaultValue, [string environmentVariable = null], [IReadOnlyCollection canApplyTo = null]) @@ -34,8 +39,8 @@ where - It is reused as the help message of the corresponding PowerShell parameter in documents. - `defaultValue` is the default value of the config. Used for basic type validation when setting the config. - (Optional) `environmentVariable` sets to which environment variable the config is connected. Once set, the config framework will pick up the variable automatically. - - Note: the config must correspond to **one single** environment variable and it must not require special logic to parse the value. Otherwise please check out [todo]. -- (Optional) `canApplyTo` defines at which levels the config can apply to. There are three levels in total: `AppliesTo.Az`, `AppliesTo.Module`, `AppliesTo.Cmdlet`. By default all of them are included. For more details, see [todo]. + - Note: the config must correspond to **one single** environment variable and it must not require special logic to parse the value. Otherwise please check out [Parsing Environment Variables](#parsing-environment-variables). +- (Optional) `canApplyTo` defines at which levels the config can apply to. There are three levels in total: `AppliesTo.Az`, `AppliesTo.Module`, `AppliesTo.Cmdlet`. By default all of them are included. For more details, see [About AppliesTo](#about-appliesto). Here is a sample definition: @@ -67,11 +72,11 @@ internal class DisplayBreakingChangeWarningsConfig : TypedConfig } ``` -Definining configs in the standard way is more customizable than the simple way, for example when it comes to validating values and parsing enviroment variables. For more, see [todo]. +Defining configs in the standard way is more customizable than the simple way, for example when it comes to validating values and parsing environment variables. For more, see [Customizing Config Definitions](#customizing-config-definitions). ### Step 2: Register the Config -Either way the config is defined, instanciate it and call [`IConfigManager.RegisterConfig(ConfigDefinition config)`](https://github.com/Azure/azure-powershell-common/blob/8d70507d41a3698b5b131df61f14e329d7a6eb41/src/Authentication.Abstractions/Interfaces/IConfigManager.cs#L30) in [`ConfigInitializer.RegisterConfigs(IConfigManager configManager)`](https://github.com/Azure/azure-powershell/blob/304e15c84071fee02622734c4e5f12c05baa77d2/src/Accounts/Authentication/Config/ConfigInitializer.cs#L192). For example: +Either way the config is defined, instantiate it and call [`IConfigManager.RegisterConfig(ConfigDefinition config)`](https://github.com/Azure/azure-powershell-common/blob/8d70507d41a3698b5b131df61f14e329d7a6eb41/src/Authentication.Abstractions/Interfaces/IConfigManager.cs#L30) in [`ConfigInitializer.RegisterConfigs(IConfigManager configManager)`](https://github.com/Azure/azure-powershell/blob/304e15c84071fee02622734c4e5f12c05baa77d2/src/Accounts/Authentication/Config/ConfigInitializer.cs#L192). For example: ```csharp configManager.RegisterConfig(new DisplayBreakingChangeWarningsConfig()); @@ -92,9 +97,9 @@ AzureSession.Instance.TryGetComponent(nameof(IConfigManager), ou string subscriptionFromConfig = configManager.GetConfigValue(ConfigKeys.DefaultSubscriptionForLogin, MyInvocation); ``` -Note that although `invocation` is optional, if the config can apply to either `AppliesTo.Module` or `AppliesTo.Cmdlet` (see [todo]), it must be `MyInvocation`. Alternatively, it could be a good idea to always pass in `MyInvocation`. +Note that although `invocation` is optional, if the config can apply to either `AppliesTo.Module` or `AppliesTo.Cmdlet` (see [About AppliesTo](#about-appliesto)), it must be `MyInvocation`. Alternatively, it could be a good idea to always pass in `MyInvocation`. -## Lesser Topics +## Customizing Config Definitions ### About AppliesTo @@ -110,7 +115,7 @@ The `IReadOnlyCollection ConfigDefinition.CanApplyTo { get; }` proper By default, when setting the value of a config, the type of the value is validated. If you want to implement your own validation, override `void TypedConfig.Validate(object value)`, throw an exception when the value is invalid. -```powershell +```csharp public override void Validate(object value) { // do not forget to call `base` so type is still checked @@ -150,5 +155,3 @@ public override string ParseFromEnvironmentVariables(IReadOnlyDictionary Date: Thu, 9 Jun 2022 10:44:13 +0800 Subject: [PATCH 16/16] Update using-config-framework.md --- .../development-docs/using-config-framework.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/documentation/development-docs/using-config-framework.md b/documentation/development-docs/using-config-framework.md index 435de4c08367..74a408c1c618 100644 --- a/documentation/development-docs/using-config-framework.md +++ b/documentation/development-docs/using-config-framework.md @@ -17,7 +17,7 @@ The config framework was introduced in Az 8, May 2022 to set up a standard of how configs are used by both developers and end users of Azure PowerShell. -This document will go over 2 most common scenarios for developers. As for how to set configs please refer to [Update-AzConfig](https://docs.microsoft.com/powershell/module/az.accounts/update-azconfig). +This document will go over two most common scenarios for developers. As for how to use the config framework in PowerShell please refer to [Update-AzConfig](https://docs.microsoft.com/powershell/module/az.accounts/update-azconfig). ## Guide: How to Add a New Config @@ -34,13 +34,14 @@ where - `TValue` is the type of the value of the config, for example `int` or `bool`. - `key` is the unique key of the config. It is used when user gets or sets the config. - It must be defined in [src/shared/ConfigKeys.cs](https://github.com/Azure/azure-powershell/blob/main/src/shared/ConfigKeys.cs) so that it can be referenced in any project. - - It is reused as a parameter name of cmdlets that operate on configs, for example `Get-AzConfig`, so it must follow the naming conventions. See [Parameter Best Practices](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/design-guidelines/parameter-best-practices.md#parameter-best-practices). + - If the config will be used in the [azure-powershell-common] solution, it must also be defined in [src/Authentication.Abstractions/Models/ConfigKeysForCommon.cs](https://github.com/Azure/azure-powershell-common/blob/main/src/Authentication.Abstractions/Models/ConfigKeysForCommon.cs). + - It is reused as a parameter name of cmdlets that operate on configs, for example `Get-AzConfig`, so it must **follow the PowerShell naming conventions**. See [Parameter Best Practices](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/design-guidelines/parameter-best-practices.md#parameter-best-practices). - `helpMessage` is the help message or description of the config. - It is reused as the help message of the corresponding PowerShell parameter in documents. - `defaultValue` is the default value of the config. Used for basic type validation when setting the config. -- (Optional) `environmentVariable` sets to which environment variable the config is connected. Once set, the config framework will pick up the variable automatically. +- _(Optional)_ `environmentVariable` sets to which environment variable the config is connected. Once set, the config framework will pick up the variable automatically. - Note: the config must correspond to **one single** environment variable and it must not require special logic to parse the value. Otherwise please check out [Parsing Environment Variables](#parsing-environment-variables). -- (Optional) `canApplyTo` defines at which levels the config can apply to. There are three levels in total: `AppliesTo.Az`, `AppliesTo.Module`, `AppliesTo.Cmdlet`. By default all of them are included. For more details, see [About AppliesTo](#about-appliesto). +- _(Optional)_ `canApplyTo` defines at which levels the config can apply to. There are three levels in total: `AppliesTo.Az`, `AppliesTo.Module`, `AppliesTo.Cmdlet`. By default all of them are included. For more details, see [About AppliesTo](#about-appliesto). Here is a sample definition: @@ -72,7 +73,7 @@ internal class DisplayBreakingChangeWarningsConfig : TypedConfig } ``` -Defining configs in the standard way is more customizable than the simple way, for example when it comes to validating values and parsing environment variables. For more, see [Customizing Config Definitions](#customizing-config-definitions). +Defining configs in the standard way is more _flexible_ than the simple way, for example when it comes to validating values and parsing environment variables. For more, see [Customizing Config Definitions](#customizing-config-definitions). ### Step 2: Register the Config @@ -82,7 +83,7 @@ Either way the config is defined, instantiate it and call [`IConfigManager.Regis configManager.RegisterConfig(new DisplayBreakingChangeWarningsConfig()); ``` -Up until now, you are able to test this new config with `Get-AzConfig`, `Update-AzConfig` and `Clear-AzConfig`. For more, run `Get-Help Get-AzConfig`. +Up until now, you are able to test this new config with PowerShell cmdlets `Get-AzConfig`, `Update-AzConfig` and `Clear-AzConfig`. For more, run `Get-Help Get-AzConfig`. ### Step 3: Regenerate Help Documents @@ -97,7 +98,7 @@ AzureSession.Instance.TryGetComponent(nameof(IConfigManager), ou string subscriptionFromConfig = configManager.GetConfigValue(ConfigKeys.DefaultSubscriptionForLogin, MyInvocation); ``` -Note that although `invocation` is optional, if the config can apply to either `AppliesTo.Module` or `AppliesTo.Cmdlet` (see [About AppliesTo](#about-appliesto)), it must be `MyInvocation`. Alternatively, it could be a good idea to always pass in `MyInvocation`. +Note that although `invocation` is optional, if the config can apply to either `AppliesTo.Module` or `AppliesTo.Cmdlet` (see [About AppliesTo](#about-appliesto)), it must be `MyInvocation`. Alternatively, **it is best practice to always pass in `MyInvocation`**. ## Customizing Config Definitions @@ -113,7 +114,7 @@ The `IReadOnlyCollection ConfigDefinition.CanApplyTo { get; }` proper ### Validation of Config Value -By default, when setting the value of a config, the type of the value is validated. If you want to implement your own validation, override `void TypedConfig.Validate(object value)`, throw an exception when the value is invalid. +By default, when user sets a config, the type of the value is validated. If you want to implement your own validation, override `void TypedConfig.Validate(object value)`, throw an exception when the value is invalid. ```csharp public override void Validate(object value)