|
3 | 3 | * SPDX-License-Identifier: Apache-2.0 |
4 | 4 | */ |
5 | 5 |
|
6 | | -import { FeatureValue } from '../client/codewhispereruserclient' |
| 6 | +import { Customization, FeatureValue } from '../client/codewhispereruserclient' |
7 | 7 | import { codeWhispererClient as client } from '../client/codewhisperer' |
8 | 8 | import { AuthUtil } from '../util/authUtil' |
9 | 9 | import { getLogger } from '../../shared/logger' |
| 10 | +import { isBuilderIdConnection, isIdcSsoConnection } from '../../auth/connection' |
10 | 11 |
|
11 | 12 | export class FeatureContext { |
12 | 13 | constructor(public name: string, public variation: string, public value: FeatureValue) {} |
13 | 14 | } |
14 | 15 |
|
15 | 16 | const testFeatureName = 'testFeature' |
| 17 | +const customizationArnOverrideName = 'customizationArnOverride' |
16 | 18 | const featureConfigPollIntervalInMs = 30 * 60 * 1000 // 30 mins |
17 | 19 |
|
18 | 20 | // TODO: add real feature later |
19 | 21 | export const featureDefinitions = new Map([ |
20 | 22 | [testFeatureName, new FeatureContext(testFeatureName, 'CONTROL', { stringValue: 'testValue' })], |
| 23 | + [ |
| 24 | + customizationArnOverrideName, |
| 25 | + new FeatureContext(customizationArnOverrideName, 'customizationARN', { stringValue: '' }), |
| 26 | + ], |
21 | 27 | ]) |
22 | 28 |
|
23 | 29 | export class FeatureConfigProvider { |
@@ -53,6 +59,39 @@ export class FeatureConfigProvider { |
53 | 59 | new FeatureContext(evaluation.feature, evaluation.variation, evaluation.value) |
54 | 60 | ) |
55 | 61 | }) |
| 62 | + |
| 63 | + const customizationArnOverride = this.featureConfigs.get(customizationArnOverrideName)?.value?.stringValue |
| 64 | + if (customizationArnOverride !== undefined) { |
| 65 | + // Double check if server-side wrongly returns a customizationArn to BID users |
| 66 | + if (isBuilderIdConnection(AuthUtil.instance.conn)) { |
| 67 | + this.featureConfigs.delete(customizationArnOverrideName) |
| 68 | + } else if (isIdcSsoConnection(AuthUtil.instance.conn)) { |
| 69 | + let availableCustomizations = undefined |
| 70 | + try { |
| 71 | + const items: Customization[] = [] |
| 72 | + const response = await client.listAvailableCustomizations() |
| 73 | + response |
| 74 | + .map( |
| 75 | + listAvailableCustomizationsResponse => |
| 76 | + listAvailableCustomizationsResponse.customizations |
| 77 | + ) |
| 78 | + .forEach(customizations => { |
| 79 | + items.push(...customizations) |
| 80 | + }) |
| 81 | + availableCustomizations = items.map(c => c.arn) |
| 82 | + } catch (e) { |
| 83 | + getLogger().debug('amazonq: Failed to list available customizations') |
| 84 | + } |
| 85 | + |
| 86 | + // If customizationArn from A/B is not available in listAvailableCustomizations response, don't use this value |
| 87 | + if (!availableCustomizations?.includes(customizationArnOverride)) { |
| 88 | + getLogger().debug( |
| 89 | + `Customization arn ${customizationArnOverride} not available in listAvailableCustomizations, not using` |
| 90 | + ) |
| 91 | + this.featureConfigs.delete(customizationArnOverrideName) |
| 92 | + } |
| 93 | + } |
| 94 | + } |
56 | 95 | } catch (e) { |
57 | 96 | getLogger().error(`CodeWhisperer: Error when fetching feature configs ${e}`, e) |
58 | 97 | } |
@@ -82,6 +121,10 @@ export class FeatureConfigProvider { |
82 | 121 | return this.getFeatureValueForKey(testFeatureName).stringValue |
83 | 122 | } |
84 | 123 |
|
| 124 | + getCustomizationArnOverride(): string | undefined { |
| 125 | + return this.getFeatureValueForKey(customizationArnOverrideName).stringValue |
| 126 | + } |
| 127 | + |
85 | 128 | // Get the feature value for the given key. |
86 | 129 | // In case of a misconfiguration, it will return a default feature value of Boolean true. |
87 | 130 | private getFeatureValueForKey(name: string): FeatureValue { |
|
0 commit comments