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

feat: add console command to storage category #10981

Merged
merged 15 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/amplify-category-storage/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function canResourceBeTransformed(context: $TSContext, resourceName: stri
export const category = "storage";

// @public (undocumented)
function console_2(context: any): Promise<void>;
const console_2: (context: $TSContext) => Promise<void>;
export { console_2 as console }

// @public (undocumented)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {
$TSContext, stateManager,
} from 'amplify-cli-core';
import { Printer, printer } from 'amplify-prompts';
import { run } from '../../commands/storage/console';
import * as providerController from '../../provider-utils/awscloudformation/index';

jest.mock('../../provider-utils/awscloudformation/index');
jest.mock('amplify-cli-core');
jest.mock('amplify-prompts');

const providerControllerMock = providerController as jest.Mocked<typeof providerController>;
const getMetaMock = stateManager.getMeta as jest.MockedFunction<typeof stateManager.getMeta>;
const printerMock = printer as jest.Mocked<Printer>;

describe('console command tests', () => {
const provider = 'awscloudformation';
let mockContext: $TSContext;

beforeEach(() => {
jest.clearAllMocks();
mockContext = {
amplify: {},
} as unknown as $TSContext;
});

it('calls open console', async () => {
const amplifyMetaMock = {
storage: {
TestTable: {
service: 'DynamoDB',
providerPlugin: 'awscloudformation',
},
},
};
getMetaMock.mockReturnValue(amplifyMetaMock);
const service = 'DynamoDB';
mockContext.amplify.serviceSelectionPrompt = jest.fn().mockImplementation(async () => ({ service, providerName: provider }));

await run(mockContext);

expect(providerControllerMock.console).toHaveBeenCalledWith(amplifyMetaMock, provider, service);
});

it('print error message when no resources in storage category', async () => {
getMetaMock.mockReturnValue({});
const service = 'DynamoDB';
mockContext.amplify.serviceSelectionPrompt = jest.fn().mockImplementation(async () => ({ service, providerName: provider }));

await run(mockContext);

expect(printerMock.error).toBeCalledWith('Storage has NOT been added to this project.');
expect(providerControllerMock.console).not.toBeCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { open } from 'amplify-cli-core';
import { console } from '../../../provider-utils/awscloudformation';

jest.mock('amplify-cli-core');

const openMock = open as jest.MockedFunction<typeof open>;

describe('awscloudformation function provider', () => {
const provider = 'awscloudformation';
beforeEach(() => jest.clearAllMocks());

it('opens the DynamoDB console', async () => {
const service = 'DynamoDB';
const amplifyMetaMock = {
storage: {
TestTable: {
service: 'DynamoDB',
providerPlugin: 'awscloudformation',
output: {
PartitionKeyName: 'id',
Region: 'us-east-1',
Name: 'TestTable-test',
},
},
},
};

await console(amplifyMetaMock, provider, service);

expect(openMock).toBeCalledWith('https://us-east-1.console.aws.amazon.com/dynamodbv2/home?region=us-east-1#table?name=TestTable-test&tab=overview', { wait: false });
});

it('opens the S3 console', async () => {
const service = 'S3';
const amplifyMetaMock = {
storage: {
TestTable: {
service: 'S3',
providerPlugin: 'awscloudformation',
output: {
Region: 'us-east-1',
BucketName: 'TestBucket-test',
},
},
},
};

await console(amplifyMetaMock, provider, service);

expect(openMock).toBeCalledWith('https://s3.console.aws.amazon.com/s3/buckets/TestBucket-test?region=us-east-1', { wait: false });
});
});
2 changes: 2 additions & 0 deletions packages/amplify-category-storage/src/commands/storage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/* eslint-disable jsdoc/require-jsdoc, jsdoc/require-description */
import { $TSContext } from 'amplify-cli-core';
import { printer } from 'amplify-prompts';
import * as path from 'path';
import { categoryName } from '../constants';

export { categoryName as name } from '../constants';
import { run as runHelp } from './storage/help';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { printer } from 'amplify-prompts';
import { categoryName } from '../../constants';
import { console } from '../..';

export const name = 'console'; // subcommand

export async function run() {
printer.info(`to be implemented: ${categoryName} ${name}`);
}
export const run = console;
52 changes: 39 additions & 13 deletions packages/amplify-category-storage/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { $TSAny, $TSContext, AmplifyCategories, AmplifySupportedService, IAmplifyResource } from 'amplify-cli-core';
/* eslint-disable jsdoc/require-jsdoc, jsdoc/require-description */
import {
$TSAny, $TSContext, AmplifyCategories, AmplifySupportedService, IAmplifyResource, stateManager,
} from 'amplify-cli-core';
import { printer } from 'amplify-prompts';
import {
validateAddStorageRequest,
Expand All @@ -25,12 +28,13 @@ import {
headlessRemoveStorage,
headlessUpdateStorage,
} from './provider-utils/awscloudformation/storage-configuration-helpers';

export { categoryName as category } from './constants';
export {
S3UserInputs,
S3UserInputTriggerFunctionParams,
} from './provider-utils/awscloudformation/service-walkthrough-types/s3-user-input-types';
//S3-Control-API used by Predictions
// S3-Control-API used by Predictions
export {
s3AddStorageLambdaTrigger,
s3CreateStorageResource,
Expand Down Expand Up @@ -75,9 +79,33 @@ export async function add(context: any, providerName: any, service: any) {
return providerController.addResource(context, AmplifyCategories.STORAGE, service, options);
}

export async function console(context: any) {
printer.info(`to be implemented: ${AmplifyCategories.STORAGE} console`);
}
/**
* Open AWS Management Console for resources of storage category.
*/
export const console = async (context: $TSContext): Promise<void> => {
const { amplify } = context;
const amplifyMeta = stateManager.getMeta();
if (!amplifyMeta.storage || Object.keys(amplifyMeta.storage).length === 0) {
printer.error('Storage has NOT been added to this project.');
return;
}

const nameOverrides = {
S3: 'S3 bucket - Content (Images, audio, video, etc.)',
DynamoDB: 'DynamoDB table - NoSQL Database',
};

const servicesMetadata = ((await import(path.join(__dirname, 'provider-utils', 'supported-services'))) as $TSAny).supportedServices;

const serviceSelection = await amplify.serviceSelectionPrompt(context, categoryName, servicesMetadata, undefined, nameOverrides);

const providerController = await import(path.join(__dirname, 'provider-utils', serviceSelection.providerName, 'index'));
if (!providerController) {
printer.error('Provider not configured for this category');
return;
}
await providerController.console(amplifyMeta, serviceSelection.providerName, serviceSelection.service);
};

export async function migrateStorageCategory(context: any) {
const { projectPath, amplifyMeta } = context.migrationInfo;
Expand Down Expand Up @@ -137,14 +165,12 @@ export async function getPermissionPolicies(context: any, resourceOpsMapping: an

for (const resourceName of Object.keys(resourceOpsMapping)) {
try {
const providerPlugin =
'providerPlugin' in resourceOpsMapping[resourceName]
? resourceOpsMapping[resourceName].providerPlugin
: amplifyMeta[storageCategory][resourceName].providerPlugin;
const service =
'service' in resourceOpsMapping[resourceName]
? resourceOpsMapping[resourceName].service
: amplifyMeta[storageCategory][resourceName].service;
const providerPlugin = 'providerPlugin' in resourceOpsMapping[resourceName]
? resourceOpsMapping[resourceName].providerPlugin
: amplifyMeta[storageCategory][resourceName].providerPlugin;
const service = 'service' in resourceOpsMapping[resourceName]
? resourceOpsMapping[resourceName].service
: amplifyMeta[storageCategory][resourceName].service;

if (providerPlugin) {
const providerController = await import(`./provider-utils/${providerPlugin}`);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/* eslint-disable */
import { ensureEnvParamManager } from '@aws-amplify/amplify-environment-parameters';
import {
$TSAny, $TSContext, exitOnNextTick, JSONUtilities, NotImplementedError, stateManager,
$TSAny, $TSContext, $TSMeta, AmplifySupportedService, exitOnNextTick, JSONUtilities, NotImplementedError, open, stateManager,
} from 'amplify-cli-core';
import { printer } from 'amplify-prompts';
import { printer, prompter } from 'amplify-prompts';
import _ from 'lodash';
import { categoryName } from '../../constants';
import { importDynamoDB, importedDynamoDBEnvInit } from './import/import-dynamodb';
import { importedS3EnvInit, importS3 } from './import/import-s3';

Expand Down Expand Up @@ -164,3 +165,34 @@ const getHeadlessParams = (context: $TSContext) => {
throw new Error(`Failed to parse storage headless parameters: ${err}`);
}
}

export const console = async (amplifyMeta: $TSMeta, provider: string, service: string) => {
if (service === AmplifySupportedService.S3) {
const s3Resource = Object.values<any>(amplifyMeta[categoryName])
.filter((resource) => resource.service === service).pop();
if (!s3Resource) {
const errMessage = 'No S3 resources to open. You need to add a resource.';
printer.error(errMessage);
return;
}
const { BucketName: bucket, Region: region } = s3Resource.output;
const url = `https://s3.console.aws.amazon.com/s3/buckets/${bucket}?region=${region}`;
open(url, { wait: false });
} else if (service === AmplifySupportedService.DYNAMODB) {
type Pickchoice = { name: string, value: { tableName: string, region: string } };
const tables: Pickchoice[] = Object.values<any>(amplifyMeta[categoryName])
.filter((resource) => resource.service === service)
.map(resource => ({
name: resource.output.Name,
value: { tableName: resource.output.Name, region: resource.output.Region }
}));
if (!tables.length) {
const errMessage = 'No DynamoDB tables to open. You need to add a resource.';
printer.error(errMessage);
return;
}
const { tableName, region } = await prompter.pick<'one', Pickchoice['value']>("Select DynamoDB table to open on your browser", tables);
const url = `https://${region}.console.aws.amazon.com/dynamodbv2/home?region=${region}#table?name=${tableName}&tab=overview`;
open(url, { wait: false });
}
}
6 changes: 6 additions & 0 deletions packages/amplify-cli-core/src/help/commands-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,12 @@ export const commandsInfo: Array<CommandInfo> = [
subCommandUsage: 'amplify storage override',
subCommandFlags: [],
},
{
subCommand: 'console',
subCommandDescription: 'Opens the web console for the storage category',
subCommandUsage: 'amplify storage console',
subCommandFlags: [],
},
],
},
{
Expand Down
2 changes: 0 additions & 2 deletions packages/amplify-opensearch-simulator/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

```ts

/// <reference types="node" />

import { $TSAny } from 'amplify-cli-core';
import execa from 'execa';
import { GetPackageAssetPaths } from 'amplify-cli-core';
Expand Down