UNPKG

@aws-amplify/amplify-category-predictions

Version:

amplify-cli predictions plugin

237 lines 10.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const inferQuestions_1 = __importDefault(require("../assets/inferQuestions")); const infer_defaults_1 = __importDefault(require("../default-values/infer-defaults")); const regionMapping_1 = __importDefault(require("../assets/regionMapping")); const amplify_cli_core_1 = require("@aws-amplify/amplify-cli-core"); const amplify_prompts_1 = require("@aws-amplify/amplify-prompts"); const path = require('path'); const fs = require('fs-extra'); const enable_guest_auth_1 = require("./enable-guest-auth"); const category = 'predictions'; const parametersFileName = 'parameters.json'; const templateFilename = 'infer-template.json.ejs'; const inferTypes = ['inferModel']; const service = 'SageMaker'; async function addWalkthrough(context) { while (!checkIfAuthExists(context)) { if (await amplify_prompts_1.prompter.yesOrNo('You need to add auth (Amazon Cognito) to your project in order to add storage for user files. Do you want to add auth now?')) { await context.amplify.invokePluginMethod(context, 'auth', undefined, 'add', [context]); break; } else { context.usageData.emitSuccess(); (0, amplify_cli_core_1.exitOnNextTick)(0); } } return await configure(context); } async function updateWalkthrough(context) { const { amplify } = context; const { amplifyMeta } = amplify.getProjectDetails(); const predictionsResources = []; Object.keys(amplifyMeta[category]).forEach((resourceName) => { if (inferTypes.includes(amplifyMeta[category][resourceName].inferType)) { predictionsResources.push({ name: resourceName, value: { name: resourceName, inferType: amplifyMeta[category][resourceName].inferType }, }); } }); if (predictionsResources.length === 0) { const errMessage = 'No resources to update. You need to add a resource.'; context.print.error(errMessage); context.usageData.emitError(new amplify_cli_core_1.ResourceDoesNotExistError(errMessage)); (0, amplify_cli_core_1.exitOnNextTick)(0); return undefined; } let resourceObj = predictionsResources[0].value; if (predictionsResources.length > 1) { resourceObj = await amplify_prompts_1.prompter.pick('Which infer resource would you like to update?', predictionsResources); } return configure(context, resourceObj); } async function configure(context, resourceObj) { const { amplify } = context; const defaultValues = (0, infer_defaults_1.default)(amplify.getProjectDetails()); const projectBackendDirPath = context.amplify.pathManager.getBackendDirPath(); let parameters = {}; let inferType; if (resourceObj) { const resourceDirPath = path.join(projectBackendDirPath, category, resourceObj.name); const parametersFilePath = path.join(resourceDirPath, parametersFileName); try { parameters = amplify.readJsonFile(parametersFilePath); } catch (e) { parameters = {}; } inferType = resourceObj.inferType; parameters.resourceName = resourceObj.name; Object.assign(defaultValues, parameters); } let answers = {}; if (!parameters.resourceName) { const inferAssetsTypeInput = inferQuestions_1.default.setup.type(); answers[inferAssetsTypeInput.name] = await amplify_prompts_1.prompter.pick(inferAssetsTypeInput.message, inferAssetsTypeInput.choices); const resourceType = resourceAlreadyExists(context, answers.inferType); if (resourceType) { const errMessage = `${resourceType} has already been added to this project.`; context.print.warning(errMessage); context.usageData.emitError(new amplify_cli_core_1.ResourceAlreadyExistsError(errMessage)); (0, amplify_cli_core_1.exitOnNextTick)(0); } const inferAssetsNameInput = inferQuestions_1.default.setup.name(`${answers.inferType}${defaultValues.resourceName}`); Object.assign(answers, { [inferAssetsNameInput.name]: await amplify_prompts_1.prompter.input(inferAssetsNameInput.message, { validate: inferAssetsNameInput.validate, initial: inferAssetsNameInput.default, }), }); inferType = answers.inferType; if (inferType === 'modelInfer') { defaultValues.region = regionMapping_1.default.getAvailableRegion(context, 'SageMaker', defaultValues.region); } } Object.assign(answers, await followUpQuestions(context, defaultValues, parameters)); answers = { ...answers, service }; Object.assign(defaultValues, answers); if (answers.access === 'authAndGuest') { await (0, enable_guest_auth_1.enableGuestAuth)(context, defaultValues.resourceName, true); } const { resourceName } = defaultValues; delete defaultValues.service; delete defaultValues.region; defaultValues.inferType = inferType; const resourceDirPath = path.join(projectBackendDirPath, category, resourceName); const amplifyMetaValues = { resourceName, service, inferType, }; fs.ensureDirSync(resourceDirPath); const parametersFilePath = path.join(resourceDirPath, parametersFileName); const jsonString = JSON.stringify(defaultValues, null, 4); fs.writeFileSync(parametersFilePath, jsonString, 'utf8'); if (!parameters.resourceName) { await copyCfnTemplate(context, category, resourceName, defaultValues); } addRegionMapping(context, resourceName, inferType); return amplifyMetaValues; } function addRegionMapping(context, resourceName, inferType) { const regionMapping = regionMapping_1.default.getRegionMapping(context, service, inferType); const projectBackendDirPath = context.amplify.pathManager.getBackendDirPath(); const identifyCFNFilePath = path.join(projectBackendDirPath, category, resourceName, `${resourceName}-template.json`); const identifyCFNFile = context.amplify.readJsonFile(identifyCFNFilePath); identifyCFNFile.Mappings = regionMapping; const identifyCFNJSON = JSON.stringify(identifyCFNFile, null, 4); fs.writeFileSync(identifyCFNFilePath, identifyCFNJSON, 'utf8'); } async function copyCfnTemplate(context, categoryName, resourceName, options) { const { amplify } = context; const targetDir = amplify.pathManager.getBackendDirPath(); const pluginDir = __dirname; const copyJobs = [ { dir: pluginDir, template: `../cloudformation-templates/${templateFilename}`, target: `${targetDir}/${categoryName}/${resourceName}/${resourceName}-template.json`, }, ]; return await context.amplify.copyBatch(context, copyJobs, options); } async function followUpQuestions(context, defaultValues, parameters) { var _a; const answers = { endpointConfig: await amplify_prompts_1.prompter.pick('Would you like to create your endpoint or load an use an existing endpoint?', [ { name: 'Create an endpoint', value: 'create', }, { name: 'Import an existing endpoint', value: 'import', }, ]), }; if (answers.endpointConfig === 'import') { Object.assign(answers, await getEndpoints(context, parameters)); } if (answers.endpointConfig === 'create') { await createEndpoint(context, defaultValues); Object.assign(answers, await getEndpoints(context, parameters)); } Object.assign(answers, { access: await amplify_prompts_1.prompter.pick('Who should have access?', [ { name: 'Auth users only', value: 'auth', }, { name: 'Auth and Guest users', value: 'authAndGuest', }, ], { initial: (0, amplify_prompts_1.byValue)((_a = parameters.access) !== null && _a !== void 0 ? _a : 'auth') }), }); return answers; } function checkIfAuthExists(context) { const { amplify } = context; const { amplifyMeta } = amplify.getProjectDetails(); let authExists = false; const authServiceName = 'Cognito'; const authCategory = 'auth'; if (amplifyMeta[authCategory] && Object.keys(amplifyMeta[authCategory]).length > 0) { const categoryResources = amplifyMeta[authCategory]; Object.keys(categoryResources).forEach((resource) => { if (categoryResources[resource].service === authServiceName) { authExists = true; } }); } return authExists; } function resourceAlreadyExists(context, inferType) { const { amplify } = context; const { amplifyMeta } = amplify.getProjectDetails(); let type; if (amplifyMeta[category] && context.commandName !== 'update') { const categoryResources = amplifyMeta[category]; Object.keys(categoryResources).forEach((resource) => { if (categoryResources[resource].inferType === inferType) { type = inferType; } }); } return type; } async function getEndpoints(context, params) { const sagemaker = await context.amplify.executeProviderUtils(context, 'awscloudformation', 'getEndpoints'); const endpoints = []; const endpointMap = {}; sagemaker.Endpoints.forEach((endpoint) => { endpoints.push({ name: `${endpoint.EndpointName}` }); endpointMap[endpoint.EndpointName] = { endpointName: endpoint.EndpointName, endpointARN: endpoint.EndpointArn }; }); if (endpoints.length < 1) { const errMessage = 'No existing endpoints!'; context.print.error(errMessage); context.usageData.emitError(new amplify_cli_core_1.ResourceDoesNotExistError(errMessage)); (0, amplify_cli_core_1.exitOnNextTick)(0); } const endpoint = await amplify_prompts_1.prompter.pick('Select an endpoint: ', endpoints, { initial: (0, amplify_prompts_1.byValue)(params.endpointName) }); return endpointMap[endpoint]; } async function createEndpoint(context, defaultValues) { const endpointConsoleUrl = `https://${defaultValues.region}.console.aws.amazon.com/sagemaker/home?region=${defaultValues.region}#/endpoints/create`; await (0, amplify_cli_core_1.open)(endpointConsoleUrl, { wait: false }); context.print.info('SageMaker Console:'); context.print.success(endpointConsoleUrl); await amplify_prompts_1.prompter.input('Press enter to continue'); } module.exports = { addWalkthrough, updateWalkthrough }; //# sourceMappingURL=infer-walkthrough.js.map