Skip to content
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

Allow 3rd-party plugin to CDK override #9601

Merged
merged 6 commits into from
May 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { $TSContext } from 'amplify-cli-core';
import { AppsyncApiInputState } from '../../../../provider-utils/awscloudformation/api-input-manager/appsync-api-input-state';

jest.mock('fs-extra');
Expand Down Expand Up @@ -35,14 +36,27 @@ jest.mock('amplify-cli-core', () => ({
},
}));

const mockContext: $TSContext = {
amplify: {
getCategoryPluginInfo: (_context: $TSContext, category: string) => {
return {
packageLocation: `@aws-amplify/amplify-category-${category}`,
};
},
},
input: {
options: {},
},
} as unknown as $TSContext;

test('Api Input State -> validate cli payload manual payload', async () => {
const resourceName = 'mockResource';
const apiState = new AppsyncApiInputState(resourceName);
const apiState = new AppsyncApiInputState(mockContext, resourceName);
expect(await apiState.isCLIInputsValid()).toBe(true);
});

test('Api Input State -> validate cli payload manual payload to throw error', async () => {
const resourceName = 'mockResource';
const apiState = new AppsyncApiInputState(resourceName);
const apiState = new AppsyncApiInputState(mockContext, resourceName);
expect(apiState.isCLIInputsValid()).rejects.toThrowError();
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { $TSContext } from 'amplify-cli-core';
import { getAuthConfig } from '../../../../provider-utils/awscloudformation/utils/get-appsync-auth-config';

const getCLIInputPayload_mock = jest
Expand Down Expand Up @@ -46,10 +47,23 @@ jest.mock('../../../../provider-utils/awscloudformation/api-input-manager/appsyn
};
});

const mockContext: $TSContext = {
amplify: {
getCategoryPluginInfo: (_context: $TSContext, category: string) => {
return {
packageLocation: `@aws-amplify/amplify-category-${category}`,
};
},
},
input: {
options: {},
},
} as unknown as $TSContext;

test('test function with default auth config', async () => {
expect(await getAuthConfig('mockapiResource')).toMatchSnapshot();
expect(await getAuthConfig(mockContext, 'mockapiResource')).toMatchSnapshot();
});

test('test function with default and additional auth config', async () => {
expect(await getAuthConfig('mockapiResource')).toMatchSnapshot();
expect(await getAuthConfig(mockContext, 'mockapiResource')).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export const transformGraphQLSchemaV2 = async (context: $TSContext, options): Pr
AmplifyCategories.API,
AmplifySupportedService.APPSYNC,
'getAuthConfig',
[resources[0].resourceName],
[context, resources[0].resourceName],
);
// handle case where auth project is not migrated , if Auth not migrated above function will return empty Object
if (_.isEmpty(authConfig)) {
Expand Down Expand Up @@ -259,7 +259,7 @@ export const transformGraphQLSchemaV2 = async (context: $TSContext, options): Pr
AmplifyCategories.API,
AmplifySupportedService.APPSYNC,
'getResolverConfig',
[resources[0].resourceName],
[context, resources[0].resourceName],
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { AmplifyCategories, AmplifySupportedService, CLIInputSchemaValidator, JSONUtilities, pathManager } from 'amplify-cli-core';
import {
$TSContext,
AmplifyCategories,
AmplifySupportedService,
CLIInputSchemaValidator,
JSONUtilities,
pathManager,
} from 'amplify-cli-core';
import * as fs from 'fs-extra';
import * as path from 'path';
import { AppSyncCLIInputs } from '../service-walkthrough-types/appsync-user-input-types';
Expand All @@ -10,7 +17,7 @@ export class AppsyncApiInputState {
#service: string; //AWS service for the resource
#buildFilePath: string;

constructor(resourceName: string) {
constructor(private readonly context: $TSContext, resourceName: string) {
this.#category = AmplifyCategories.API;
this.#service = AmplifySupportedService.APPSYNC;
this.#resourceName = resourceName;
Expand All @@ -21,7 +28,7 @@ export class AppsyncApiInputState {
}

public async isCLIInputsValid(cliInputs: AppSyncCLIInputs = this.getCLIInputPayload()): Promise<boolean> {
const schemaValidator = new CLIInputSchemaValidator('appsync', this.#category, 'AppSyncCLIInputs');
const schemaValidator = new CLIInputSchemaValidator(this.context, 'appsync', this.#category, 'AppSyncCLIInputs');
return schemaValidator.validateInput(JSON.stringify(cliInputs));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,12 @@ export class ApigwInputState {
cliInputs = this.getCliInputPayload();
}

const schemaValidator = new CLIInputSchemaValidator(AmplifySupportedService.APIGW, AmplifyCategories.API, 'APIGatewayCLIInputs');
const schemaValidator = new CLIInputSchemaValidator(
this.context,
AmplifySupportedService.APIGW,
AmplifyCategories.API,
'APIGatewayCLIInputs',
);
schemaValidator.validateInput(JSONUtilities.stringify(cliInputs));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,20 +314,13 @@ class CfnApiArtifactHandler implements ApiArtifactHandler {
};
}
// deploy appsync inputs
const cliState = new AppsyncApiInputState(serviceConfig.apiName);
const cliState = new AppsyncApiInputState(this.context, serviceConfig.apiName);
await cliState.saveCLIInputPayload(appsyncCLIInputs);
return appsyncCLIInputs;
};

/**
* If the resource is migrated, updates cli-inputs.json with the specified updates
* If not migrated, this method is a noop (but still returns the schema path)
* @param updates The updates to apply
* @param apiName The api name
* @returns The gqlSchemaPath
*/
private updateAppsyncCLIInputs = async (updates: AppSyncServiceModification, apiName: string): Promise<string> => {
const cliState = new AppsyncApiInputState(apiName);
private updateAppsyncCLIInputs = async (updates: AppSyncServiceModification, apiName: string) => {
const cliState = new AppsyncApiInputState(this.context, apiName);
const gqlSchemaPath = path.join(this.getResourceDir(apiName), gqlSchemaFilename);
if (!cliState.cliInputFileExists()) {
return gqlSchemaPath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AppsyncApiInputState } from '../api-input-manager/appsync-api-input-sta
import { migrateResourceToSupportOverride } from './migrate-api-override-resource';

export const checkAppsyncApiResourceMigration = async (context: $TSContext, apiName: string, isUpdate: boolean): Promise<boolean> => {
const cliState = new AppsyncApiInputState(apiName);
const cliState = new AppsyncApiInputState(context, apiName);
if (!cliState.cliInputFileExists()) {
printer.debug('cli-inputs.json doesnt exist');
const headlessMigrate = context.input.options?.yes || context.input.options?.forcePush || context.input.options?.headless;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { $TSContext } from 'amplify-cli-core';
import { AppsyncApiInputState } from '../api-input-manager/appsync-api-input-state';
import { appSyncAuthTypeToAuthConfig } from './auth-config-to-app-sync-auth-type-bi-di-mapper';

Expand All @@ -6,8 +7,8 @@ import { appSyncAuthTypeToAuthConfig } from './auth-config-to-app-sync-auth-type
* @param resourceName
* @returns authConfig
*/
export const getAuthConfig = async (resourceName: string) => {
const cliState = new AppsyncApiInputState(resourceName);
export const getAuthConfig = async (context: $TSContext, resourceName: string) => {
const cliState = new AppsyncApiInputState(context, resourceName);
if (cliState.cliInputFileExists()) {
const appsyncInputs = cliState.getCLIInputPayload().serviceConfiguration;
return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { $TSContext } from 'amplify-cli-core';
import { AppsyncApiInputState } from '../api-input-manager/appsync-api-input-state';
import { conflictResolutionToResolverConfig } from './resolver-config-to-conflict-resolution-bi-di-mapper';

Expand All @@ -6,8 +7,8 @@ import { conflictResolutionToResolverConfig } from './resolver-config-to-conflic
* @param resourceName
* @returns resolverConfig
*/
export const getResolverConfig = async (resourceName: string) => {
const cliState = new AppsyncApiInputState(resourceName);
export const getResolverConfig = async (context: $TSContext, resourceName: string) => {
const cliState = new AppsyncApiInputState(context, resourceName);
if (cliState.cliInputFileExists()) {
const appsyncInputs = cliState.getCLIInputPayload().serviceConfiguration;
return conflictResolutionToResolverConfig(appsyncInputs.conflictResolution);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { $TSContext } from 'amplify-cli-core';
import { AuthInputState } from '../../../../provider-utils/awscloudformation/auth-inputs-manager/auth-input-state';

jest.mock('fs-extra');
Expand Down Expand Up @@ -97,14 +98,27 @@ jest.mock('amplify-cli-core', () => ({
},
}));

const mockContext: $TSContext = {
amplify: {
getCategoryPluginInfo: (_context: $TSContext, category: string) => {
return {
packageLocation: `@aws-amplify/amplify-category-${category}`,
};
},
},
input: {
options: {},
},
} as unknown as $TSContext;

test('Auth Input State -> validate cli payload manual payload', async () => {
const resourceName = 'mockResource';
const authState = new AuthInputState(resourceName);
const authState = new AuthInputState(mockContext, resourceName);
expect(await authState.isCLIInputsValid()).toBe(true);
});

test('Auth Input State -> validate cli payload manual payload to throw error', async () => {
const resourceName = 'mockResource';
const authState = new AuthInputState(resourceName);
const authState = new AuthInputState(mockContext, resourceName);
expect(authState.isCLIInputsValid()).rejects.toThrowError();
});
2 changes: 1 addition & 1 deletion packages/amplify-category-auth/src/commands/auth/remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const run = async (context: $TSContext) => {
const resource = await amplify.removeResource(context, category, resourceName);
if (resource?.service === AmplifySupportedService.COGNITOUSERPOOLGROUPS) {
// update cli input here
const cliState = new AuthInputState(authResourceName[0]);
const cliState = new AuthInputState(context, authResourceName[0]);
const cliInputPayload = cliState.getCLIInputPayload();
cliInputPayload.cognitoConfig.userPoolGroupList = [];
await cliState.saveCLIInputPayload(cliInputPayload);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class AuthInputState extends CategoryInputState {
#service: string; //AWS service for the resource
#buildFilePath: string;

constructor(resourceName: string) {
constructor(private readonly context: $TSContext, resourceName: string) {
super(resourceName);
this.#category = AmplifyCategories.AUTH;
this.#service = AmplifySupportedService.COGNITO;
Expand All @@ -33,7 +33,7 @@ export class AuthInputState extends CategoryInputState {
}

public async isCLIInputsValid(cliInputs: CognitoCLIInputs = this.getCLIInputPayload()): Promise<boolean> {
const schemaValidator = new CLIInputSchemaValidator(this.#service, this.#category, 'CognitoCLIInputs');
const schemaValidator = new CLIInputSchemaValidator(this.context, this.#service, this.#category, 'CognitoCLIInputs');
return schemaValidator.validateInput(JSON.stringify(cliInputs));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class AmplifyAuthTransform extends AmplifyCategoryTransform {
public async transform(context: $TSContext): Promise<Template> {
// parse Input data
// validating cli-inputs
const cliState = new AuthInputState(this.resourceName);
const cliState = new AuthInputState(context, this.resourceName);
this._cliInputs = cliState.getCLIInputPayload();
this._cognitoStackProps = await this.generateStackProps(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class AmplifyUserPoolGroupTransform extends AmplifyCategoryTransform {
*/
public async transform(context: $TSContext): Promise<Template> {
// parse Input data
const userPoolGroupStackOptions = await this.generateStackProps();
const userPoolGroupStackOptions = await this.generateStackProps(context);

// generate cfn Constructs and AmplifyRootStackTemplate object to get overridden
await this.generateStackResources(userPoolGroupStackOptions);
Expand Down Expand Up @@ -213,28 +213,10 @@ export class AmplifyUserPoolGroupTransform extends AmplifyCategoryTransform {
/**
* Object required to generate Stack using cdk
*/
private generateStackProps = async (): Promise<AmplifyUserPoolGroupStackOptions> => {
private generateStackProps = async (context: $TSContext): Promise<AmplifyUserPoolGroupStackOptions> => {
const resourceDirPath = path.join(pathManager.getBackendDirPath(), 'auth', 'userPoolGroups', 'user-pool-group-precedence.json');
const groups = JSONUtilities.readJson<UserPoolGroupMetadata[]>(resourceDirPath, { throwIfNotExist: true }) ?? [];

// adding custom policies defined in user-pool-group-precedence.json file
groups.forEach(groupItr => {
const group = groupItr;
if (group.customPolicies) {
group.customPolicies.forEach((policyItr: $TSAny) => {
const policy = policyItr;
if (policy?.PolicyDocument?.Statement) {
policy.PolicyDocument.Statement.forEach((statementItr: { Resource: string | string[] | $TSObject; }) => {
const statement = statementItr;
if (statement.Resource.includes('${env}')) {
statement.Resource = { 'Fn::Sub': [statement.Resource, { env: { Ref: 'env' } }] };
}
});
}
});
}
});
const cliState = new AuthInputState(this._authResourceName);
const groups = JSONUtilities.readJson(resourceDirPath, { throwIfNotExist: true });
const cliState = new AuthInputState(context, this._authResourceName);
this._cliInputs = cliState.getCLIInputPayload();
const { identityPoolName } = this._cliInputs.cognitoConfig;
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const getAddAuthHandler =

// move this function outside of AddHandler
try {
const cliState = new AuthInputState(cognitoCLIInputs.cognitoConfig.resourceName);
const cliState = new AuthInputState(context, cognitoCLIInputs.cognitoConfig.resourceName);
// saving cli-inputs except secrets
await cliState.saveCLIInputPayload(cognitoCLIInputs);
// cdk transformation in this function
Expand Down Expand Up @@ -148,7 +148,7 @@ export const getUpdateAuthHandler = (context: $TSContext) => async (request: Ser
cognitoConfig: cliInputs,
};
try {
const cliState = new AuthInputState(cognitoCLIInputs.cognitoConfig.resourceName);
const cliState = new AuthInputState(context, cognitoCLIInputs.cognitoConfig.resourceName);
const triggers = cognitoCLIInputs.cognitoConfig.triggers;
// convert triggers to JSON as overided in defaults
if (triggers && typeof triggers === 'string') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ import { AuthInputState } from '../auth-inputs-manager/auth-input-state';
*/
export const attachPrevParamsToContext = async (context: any) => {
const resourceName = await getAuthResourceName(context);
const cliState = new AuthInputState(resourceName);
const cliState = new AuthInputState(context, resourceName);
context.updatingAuth = await cliState.loadResourceParameters(context, cliState.getCLIInputPayload());
};
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async function loadResourceParametersLegacyCode(authResourceName: string): Promi
return userPoolMessageConfig;
}
export const loadResourceParameters = async (context: $TSContext, authResourceName: string): Promise<UserPoolMessageConfiguration> => {
const cliState = new AuthInputState(authResourceName);
const cliState = new AuthInputState(context, authResourceName);
let userPoolMessageConfig;
try {
userPoolMessageConfig = (await cliState.loadResourceParameters(context, cliState.getCLIInputPayload())) as UserPoolMessageConfiguration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const checkAuthResourceMigration = async (context: $TSContext, authName:
// check if its imported auth
const { imported } = context.amplify.getImportedAuthProperties(context);
if (!imported) {
const cliState = new AuthInputState(authName);
const cliState = new AuthInputState(context, authName);
if (!cliState.cliInputFileExists()) {
printer.debug("cli-inputs.json doesn't exist");
// put spinner here
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* These tests test the DDBStackTransform and run the cdk builder tool which is used within this file */

import { $TSContext } from 'amplify-cli-core';
import { DDBStackTransform } from '../../../../provider-utils/awscloudformation/cdk-stack-builder/ddb-stack-transform';
import {
DynamoDBCLIInputs,
Expand Down Expand Up @@ -32,6 +33,23 @@ jest.mock('path', () => ({
jest.mock('../../../../provider-utils/awscloudformation/service-walkthroughs/dynamoDB-input-state');

describe('Test DDB transform generates correct CFN template', () => {
let mockContext: $TSContext;

beforeEach(() => {
mockContext = {
amplify: {
getCategoryPluginInfo: (_context: $TSContext, category: string) => {
return {
packageLocation: `@aws-amplify/amplify-category-${category}`,
};
},
},
input: {
options: {},
},
} as unknown as $TSContext;
});

afterEach(() => {
jest.clearAllMocks();
});
Expand Down Expand Up @@ -69,7 +87,7 @@ describe('Test DDB transform generates correct CFN template', () => {
};

jest.spyOn(DynamoDBInputState.prototype, 'getCliInputPayload').mockImplementation(() => cliInputsJSON);
const ddbTransform = new DDBStackTransform(resourceName);
const ddbTransform = new DDBStackTransform(mockContext, resourceName);
await ddbTransform.transform();
expect(ddbTransform._cfn).toMatchSnapshot();
expect(ddbTransform._cfnInputParams).toMatchSnapshot();
Expand Down