Skip to content

Commit

Permalink
fix: update pinpoint regions (#12379)
Browse files Browse the repository at this point in the history
  • Loading branch information
lazpavel committed Apr 12, 2023
1 parent d578c81 commit c218dd4
Show file tree
Hide file tree
Showing 24 changed files with 255 additions and 159 deletions.
3 changes: 3 additions & 0 deletions packages/amplify-category-analytics/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { IAnalyticsResource } from '@aws-amplify/amplify-cli-core';
import { IPluginCapabilityAPIResponse } from '@aws-amplify/amplify-cli-core';
import { NotificationChannels } from '@aws-amplify/amplify-cli-core';

// @public (undocumented)
export const analyticsGetPinpointRegionMapping: () => Record<string, string>;

// @public (undocumented)
export const analyticsPluginAPICreateResource: (context: $TSContext, resourceProviderServiceName: string) => Promise<IAmplifyResource>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { addResource } from './provider-utils/awscloudformation/index';
import { analyticsPush } from './commands/analytics';
import { invokeAuthPush } from './plugin-client-api-auth';
import { invokeNotificationsAPIGetAvailableChannelNames } from './plugin-client-api-notifications';
import { pinpointHasInAppMessagingPolicy } from './utils/pinpoint-helper';
import { getPinpointRegionMapping, pinpointHasInAppMessagingPolicy } from './utils/pinpoint-helper';
import { getAnalyticsResources } from './utils/analytics-helper';
import { analyticsMigrations } from './migrations';
import { LocalEnvInfo } from '@aws-amplify/amplify-cli-core';
Expand Down Expand Up @@ -341,3 +341,5 @@ export const analyticsPluginAPIPinpointHasInAppMessagingPolicy = async (context:
* Exposes the analytics migration API
*/
export const analyticsPluginAPIMigrations = (context: $TSContext): Promise<void> => analyticsMigrations(context);

export const analyticsGetPinpointRegionMapping = (): Record<string, string> => getPinpointRegionMapping();
1 change: 1 addition & 0 deletions packages/amplify-category-analytics/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export {
analyticsPluginAPICreateResource,
analyticsPluginAPIToggleNotificationChannel,
analyticsPluginAPIPinpointHasInAppMessagingPolicy,
analyticsGetPinpointRegionMapping,
analyticsPluginAPIMigrations,
analyticsPluginAPIPostPush,
analyticsPluginAPIPush,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const inAppMessagingMigrationCheck = async (context: $TSContext): Promise
templateFileName,
);
const { cfnTemplate } = readCFNTemplate(templateSourceFilePath);
cfnTemplate.Mappings = await getPinpointRegionMappings(context);
cfnTemplate.Mappings = await getPinpointRegionMappings();
await writeCFNTemplate(cfnTemplate, templateFilePath);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ const writeCfnFile = async (context: $TSContext, resourceDirPath: string, force
if (!fs.existsSync(templateFilePath) || force) {
const templateSourceFilePath = path.join(__dirname, '..', 'cloudformation-templates', templateFileName);
const templateSource = context.amplify.readJsonFile(templateSourceFilePath);
templateSource.Mappings = await getPinpointRegionMappings(context);
templateSource.Mappings = await getPinpointRegionMappings();
JSONUtilities.writeJson(templateFilePath, templateSource);
}
};
Expand Down
39 changes: 31 additions & 8 deletions packages/amplify-category-analytics/src/utils/pinpoint-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
$TSMeta,
AmplifyCategories,
stateManager,
FeatureFlags,
} from '@aws-amplify/amplify-cli-core';
import { printer } from '@aws-amplify/amplify-prompts';
import * as path from 'path';
Expand Down Expand Up @@ -125,21 +126,43 @@ export const getNotificationsCategoryHasPinpointIfExists = (): PinpointApp | und
/**
* returns provider pinpoint region mapping
*/
export const getPinpointRegionMappings = async (context: $TSContext): Promise<Record<string, $TSAny>> => {
export const getPinpointRegionMappings = async (): Promise<Record<string, $TSAny>> => {
const Mappings: Record<string, $TSAny> = {
RegionMapping: {},
};
const regionMapping: $TSAny = await context.amplify.invokePluginMethod(
context,
'awscloudformation',
undefined,
'getPinpointRegionMapping',
[],
);
const regionMapping = getPinpointRegionMapping();
Object.keys(regionMapping).forEach((region) => {
Mappings.RegionMapping[region] = {
pinpointRegion: regionMapping[region],
};
});
return Mappings;
};

export const getPinpointRegionMapping = (): { [key: string]: string } => {
const latestPinpointRegions = FeatureFlags.getNumber('latestRegionSupport.pinpoint');

return {
'us-east-1': 'us-east-1',
'us-east-2': latestPinpointRegions ? 'us-east-2' : 'us-east-1',
'sa-east-1': 'us-east-1',
'ca-central-1': latestPinpointRegions >= 1 ? 'ca-central-1' : 'us-east-1',
'us-west-1': 'us-west-2',
'us-west-2': 'us-west-2',
'cn-north-1': 'us-west-2',
'cn-northwest-1': 'us-west-2',
'ap-south-1': latestPinpointRegions >= 1 ? 'ap-south-1' : 'us-east-1',
'ap-northeast-3': 'us-west-2',
'ap-northeast-2': latestPinpointRegions >= 1 ? 'ap-northeast-2' : 'us-east-1',
'ap-southeast-1': latestPinpointRegions >= 1 ? 'ap-southeast-1' : 'us-east-1',
'ap-southeast-2': latestPinpointRegions >= 1 ? 'ap-southeast-2' : 'us-east-1',
'ap-northeast-1': latestPinpointRegions >= 1 ? 'ap-northeast-1' : 'us-east-1',
'eu-central-1': 'eu-central-1',
'eu-north-1': 'eu-central-1',
'eu-south-1': 'eu-central-1',
'eu-west-1': 'eu-west-1',
'eu-west-2': latestPinpointRegions >= 1 ? 'eu-west-2' : 'eu-west-1',
'eu-west-3': 'eu-west-1',
'me-south-1': 'ap-south-1',
};
};
5 changes: 4 additions & 1 deletion packages/amplify-category-notifications/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@
"@aws-amplify/amplify-cli-core": "4.0.2",
"@aws-amplify/amplify-environment-parameters": "1.4.2",
"@aws-amplify/amplify-prompts": "2.6.7",
"@aws-amplify/amplify-provider-awscloudformation": "8.0.4",
"aws-sdk": "^2.1350.0",
"chalk": "^4.1.1",
"fs-extra": "^8.1.0",
"lodash": "^4.17.21",
"ora": "^4.0.3",
"promise-sequential": "^1.1.1"
"promise-sequential": "^1.1.1",
"proxy-agent": "^5.0.0"
},
"jest": {
"testURL": "http://localhost",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ const getError = async <TError>(call: () => unknown): Promise<TError> => {
}
};

jest.mock('@aws-amplify/amplify-cli-core', () => {
return {
...(jest.requireActual('@aws-amplify/amplify-cli-core') as {}),
FeatureFlags: {
getBoolean: jest.fn(),
getNumber: jest.fn(),
getObject: jest.fn(),
getString: jest.fn(),
},
};
});

describe('channel-APNS', () => {
const mockServiceOutput: $TSAny = {};
const mockChannelOutput = { Enabled: true };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ import { ChannelAction, ChannelConfigDeploymentType, IChannelAPIResponse } from
import { $TSAny, $TSContext, AmplifyCategories, AmplifySupportedService } from '@aws-amplify/amplify-cli-core';
import { ChannelType } from '../notifications-backend-cfg-channel-api';

jest.mock('@aws-amplify/amplify-cli-core', () => {
return {
...(jest.requireActual('@aws-amplify/amplify-cli-core') as {}),
FeatureFlags: {
getBoolean: jest.fn(),
getNumber: jest.fn(),
getObject: jest.fn(),
getString: jest.fn(),
},
};
});

jest.mock('@aws-amplify/amplify-prompts');
const prompterMock = prompter as jest.Mocked<typeof prompter>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ import * as channelFCM from '../channel-fcm';
import { ChannelAction, ChannelConfigDeploymentType, IChannelAPIResponse } from '../channel-types';
import { ChannelType } from '../notifications-backend-cfg-channel-api';

jest.mock('@aws-amplify/amplify-cli-core', () => {
return {
...(jest.requireActual('@aws-amplify/amplify-cli-core') as {}),
FeatureFlags: {
getBoolean: jest.fn(),
getNumber: jest.fn(),
getObject: jest.fn(),
getString: jest.fn(),
},
};
});

const apiKey = 'ApiKey-abc123';
jest.mock('@aws-amplify/amplify-prompts');
const prompterMock = prompter as jest.Mocked<typeof prompter>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,19 @@ import * as analyticsClient from '../plugin-client-api-analytics';

jest.mock('@aws-amplify/amplify-cli-core', () => ({
...jest.requireActual('@aws-amplify/amplify-cli-core'),
FeatureFlags: {
getBoolean: jest.fn(),
getNumber: jest.fn(),
getObject: jest.fn(),
getString: jest.fn(),
},
stateManager: {
getCurrentBackendConfig: jest.fn(),
getCurrentEnvName: jest.fn(),
getCurrentMeta: jest.fn(),
},
}));

jest.mock('ora', () => {
const mockSpinnerInstance = {
fail: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ const mockContext = {
input: { command: undefined },
} as unknown as $TSContext;

jest.mock('@aws-amplify/amplify-cli-core', () => ({
...jest.requireActual('@aws-amplify/amplify-cli-core'),
FeatureFlags: {
getBoolean: jest.fn(),
getNumber: jest.fn(),
getObject: jest.fn(),
getString: jest.fn(),
},
}));
jest.mock('../plugin-client-api-analytics', () => ({ invokeAnalyticsMigrations: jest.fn() }));

describe('notifications tests', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ export const deletePinpointAppForEnv = async (context: $TSContext, envName: stri
const params = {
ApplicationId: pinpointApp.Id,
};
const pinpointClient = await getPinpointClient(context, 'delete', envName);
const pinpointClient = await getPinpointClient(context, AmplifyCategories.NOTIFICATIONS, 'delete', envName);

await authHelper.deleteRolePolicy(context);
return pinpointClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import {
$TSMeta,
$TSContext,
INotificationsResourceMeta,
pathManager,
AmplifyError,
} from '@aws-amplify/amplify-cli-core';
import { ICategoryMeta } from './notifications-amplify-meta-types';
import { invokeGetLastPushTimeStamp } from './plugin-client-api-analytics';
import { getAvailableChannels } from './notifications-backend-cfg-channel-api';
import { mapServiceRegion } from './pinpoint-helper';

/**
* Set output.channel.Enabled to true/false
Expand Down Expand Up @@ -79,8 +79,6 @@ const oneAtATimeJenkinsHash = (keyString: string): string => {
return (((hash + (hash << 15)) & 4294967295) >>> 0).toString(16);
};

const PINPOINT_PROVIDER_NAME = 'awscloudformation';

/**
* Get Notifications App from 'notifications' category of amplify-meta.json
* @param amplifyMeta optionally provide amplify meta
Expand Down Expand Up @@ -175,24 +173,6 @@ export const getDisabledChannelsFromAmplifyMeta = async (amplifyMeta?: $TSMeta):
return disabledChannelList;
};

/**
* Given the application region, get the closest pinpoint region
* @param context application context
* @returns pinpoint region
*/
export const getPinpointRegionMapping = async (context: $TSContext): Promise<string | undefined> => {
const projectPath = pathManager.findProjectRoot();
const applicationRegion = stateManager.getCurrentRegion(projectPath);
if (!applicationRegion) {
throw new AmplifyError('ConfigurationError', {
message: `Invalid Region for project at ${projectPath}`,
});
}
const providerPlugin = await import(context.amplify.getProviderPlugins(context)[PINPOINT_PROVIDER_NAME]);
const regionMapping: Record<string, string> = providerPlugin.getPinpointRegionMapping();
return applicationRegion in regionMapping ? regionMapping[applicationRegion] : undefined;
};

/**
* Create partial Notifications resource in Amplify Meta. The fields will be populated in post-push state
* @param context
Expand All @@ -205,7 +185,13 @@ export const getPinpointRegionMapping = async (context: $TSContext): Promise<str
*/
export const addPartialNotificationsAppMeta = async (context: $TSContext, notificationResourceName: string): Promise<$TSMeta> => {
const updatedAmplifyMeta = await stateManager.getMeta();
const pinpointRegion = await getPinpointRegionMapping(context);
const applicationRegion = stateManager.getCurrentRegion();
if (!applicationRegion) {
throw new AmplifyError('ConfigurationError', {
message: `Invalid Region for project`,
});
}
const pinpointRegion = await mapServiceRegion(context, applicationRegion);
// update amplify-meta with notifications metadata
return constructPartialNotificationsAppMeta(updatedAmplifyMeta, notificationResourceName, pinpointRegion);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import sequential from 'promise-sequential';
import { $TSAny, $TSContext, AmplifyError, stateManager } from '@aws-amplify/amplify-cli-core';
import { $TSAny, $TSContext, AmplifyCategories, AmplifyError, stateManager } from '@aws-amplify/amplify-cli-core';
import { printer } from '@aws-amplify/amplify-prompts';
import * as pinpointHelper from './pinpoint-helper';
import { IChannelAPIResponse, NotificationsChannelAPIModule } from './channel-types';
Expand All @@ -25,7 +25,7 @@ export const enableChannel = async (context: $TSContext, channelName: string): P
resolution: `Select a valid notification channel from the list: ${getAvailableChannels().join(', ')}`,
});
}
context.exeInfo.pinpointClient = await pinpointHelper.getPinpointClient(context, 'update', envName);
context.exeInfo.pinpointClient = await pinpointHelper.getPinpointClient(context, AmplifyCategories.NOTIFICATIONS, 'update', envName);
const channelActionHandler = await import(getChannelHandlerPath(channelName));
return channelActionHandler.enable(context);
};
Expand All @@ -36,7 +36,7 @@ export const enableChannel = async (context: $TSContext, channelName: string): P
export const disableChannel = async (context: $TSContext, channelName: string): Promise<IChannelAPIResponse | undefined> => {
const envName: string = stateManager.getCurrentEnvName() as string; // throws exception if env is not configured
if (isValidChannel(channelName)) {
context.exeInfo.pinpointClient = await pinpointHelper.getPinpointClient(context, 'update', envName);
context.exeInfo.pinpointClient = await pinpointHelper.getPinpointClient(context, AmplifyCategories.NOTIFICATIONS, 'update', envName);
const channelActionHandler = await import(getChannelHandlerPath(channelName));
return channelActionHandler.disable(context);
}
Expand Down Expand Up @@ -88,7 +88,7 @@ export const configureChannel = async (context: $TSContext, channelName: string)
const pinpointAppStatus = await getPinpointAppStatusFromMeta(context, notificationsMeta, envName);

if (channelName in ChannelType) {
context.exeInfo.pinpointClient = await pinpointHelper.getPinpointClient(context, 'update', envName);
context.exeInfo.pinpointClient = await pinpointHelper.getPinpointClient(context, AmplifyCategories.NOTIFICATIONS, 'update', envName);
if (context.exeInfo.serviceMeta.mobileHubMigrated === true) {
printer.error('No resources to update.');
return undefined;
Expand All @@ -106,7 +106,7 @@ export const configureChannel = async (context: $TSContext, channelName: string)
export const pullAllChannels = async (context: $TSContext, pinpointApp: $TSAny): Promise<Array<IChannelAPIResponse>> => {
const envName: string = stateManager.getCurrentEnvName() as string; // throws exception if env is not configured
const pullTasks: Array<$TSAny> = [];
context.exeInfo.pinpointClient = await pinpointHelper.getPinpointClient(context, 'update', envName);
context.exeInfo.pinpointClient = await pinpointHelper.getPinpointClient(context, AmplifyCategories.NOTIFICATIONS, 'update', envName);

for (const channelName of Object.keys(ChannelType)) {
const channelActionHandler: NotificationsChannelAPIModule = await import(getChannelHandlerPath(channelName));
Expand Down

0 comments on commit c218dd4

Please sign in to comment.