-
Notifications
You must be signed in to change notification settings - Fork 816
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: generate datastore models for Admin CMS to consume post-deploym…
…ent from CLI (#6771) * feat: generate datastore models for Admin CMS to consume post-deployment from CLI
- Loading branch information
1 parent
b53f256
commit 0e74b65
Showing
9 changed files
with
239 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { setupAmplifyAdminUI, getAmplifyBackendJobStatus } from '../utils/sdk-calls'; | ||
|
||
export async function enableAdminUI(appId: string, envName: string, region: string) { | ||
const setupAdminUIJobDetails = await setupAmplifyAdminUI(appId, region); | ||
|
||
const jobCompletionDetails = await pollUntilDone(setupAdminUIJobDetails.JobId, appId, envName, region, 2 * 1000, 2000 * 1000); | ||
|
||
if (jobCompletionDetails.Status === 'FAILED') { | ||
throw new Error('Setting up Admin UI failed'); | ||
} | ||
} | ||
|
||
// interval is how often to poll | ||
// timeout is how long to poll waiting for a result (0 means try forever) | ||
|
||
async function pollUntilDone(jobId: string, appId: string, envName: string, region: string, interval: number, timeout: number) { | ||
const start = Date.now(); | ||
while (true) { | ||
const jobDetails = await getAmplifyBackendJobStatus(jobId, appId, envName, region); | ||
|
||
if (jobDetails.Status === 'FAILED' || jobDetails.Status === 'COMPLETED') { | ||
// we know we're done here, return from here whatever you | ||
// want the final resolved value of the promise to be | ||
return jobDetails; | ||
} else { | ||
if (timeout !== 0 && Date.now() - start > timeout) { | ||
throw new Error(`Job Timed out for ${jobId}`); | ||
} else { | ||
// run again with a short delay | ||
await delay(interval); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// create a promise that resolves after a short delay | ||
function delay(t: number) { | ||
return new Promise(function (resolve) { | ||
setTimeout(resolve, t); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
packages/amplify-provider-awscloudformation/src/admin-modelgen.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import ora from 'ora'; | ||
import AWS from 'aws-sdk'; | ||
import { $TSContext, stateManager, pathManager, $TSAny } from 'amplify-cli-core'; | ||
import { isDataStoreEnabled } from 'graphql-transformer-core'; | ||
import * as path from 'path'; | ||
import { ProviderName as providerName } from './constants'; | ||
import { isAmplifyAdminApp } from './utils/admin-helpers'; | ||
import { AmplifyBackend } from './aws-utils/aws-amplify-backend'; | ||
|
||
export async function adminModelgen(context: $TSContext, resources: $TSAny[]) { | ||
const appSyncResources = resources.filter(resource => resource.service === 'AppSync'); | ||
|
||
if (appSyncResources.length === 0) { | ||
return; | ||
} | ||
const appSyncResource = appSyncResources[0]; | ||
const { resourceName } = appSyncResource; | ||
|
||
const amplifyMeta = stateManager.getMeta(); | ||
const localEnvInfo = stateManager.getLocalEnvInfo(); | ||
|
||
const appId = amplifyMeta?.providers?.[providerName]?.AmplifyAppId; | ||
if (!appId) { | ||
context.print.error('Could not find AmplifyAppId in amplify-meta.json.'); | ||
return; | ||
} | ||
const envName = localEnvInfo.envName; | ||
const { isAdminApp } = await isAmplifyAdminApp(appId); | ||
const isDSEnabled = await isDataStoreEnabled(path.join(pathManager.getBackendDirPath(), 'api', resourceName)); | ||
|
||
if (!isAdminApp || !isDSEnabled) { | ||
return; | ||
} | ||
// Generate DataStore Models for Admin UI CMS to consume | ||
const spinner = ora('Generating models in the cloud…\n').start(); | ||
const amplifyBackendInstance = await AmplifyBackend.getInstance(context); | ||
try { | ||
const jobStartDetails = await amplifyBackendInstance.amplifyBackend | ||
.generateBackendAPIModels({ | ||
AppId: appId, | ||
BackendEnvironmentName: envName, | ||
ResourceName: resourceName, | ||
}) | ||
.promise(); | ||
|
||
const jobCompletionDetails = await pollUntilDone( | ||
jobStartDetails.JobId, | ||
appId, | ||
envName, | ||
2 * 1000, | ||
2000 * 1000, | ||
amplifyBackendInstance.amplifyBackend, | ||
); | ||
if (jobCompletionDetails.Status === 'COMPLETED') { | ||
spinner.succeed('Successfully generated models in the cloud.'); | ||
} else { | ||
throw new Error('Modelgen job creation failed'); | ||
} | ||
} catch (e) { | ||
spinner.stop(); | ||
context.print.error(`Failed to create models in the cloud: ${e.message}`); | ||
} | ||
} | ||
|
||
// interval is how often to poll | ||
// timeout is how long to poll waiting for a result (0 means try forever) | ||
|
||
async function pollUntilDone( | ||
jobId: string, | ||
appId: string, | ||
backendEnvironmentName: string, | ||
interval: number, | ||
timeout: number, | ||
amplifyBackendClient: AWS.AmplifyBackend, | ||
) { | ||
const start = Date.now(); | ||
while (true) { | ||
const jobDetails = await amplifyBackendClient | ||
.getBackendJob({ | ||
JobId: jobId, | ||
AppId: appId, | ||
BackendEnvironmentName: backendEnvironmentName, | ||
}) | ||
.promise(); | ||
|
||
if (jobDetails.Status === 'FAILED' || jobDetails.Status === 'COMPLETED') { | ||
// we know we're done here, return from here whatever you | ||
// want the final resolved value of the promise to be | ||
return jobDetails; | ||
} else { | ||
if (timeout !== 0 && Date.now() - start > timeout) { | ||
throw new Error(`Job Timed out for ${jobId}`); | ||
} else { | ||
// run again with a short delay | ||
await delay(interval); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// create a promise that resolves after a short delay | ||
function delay(t: number) { | ||
return new Promise(function (resolve) { | ||
setTimeout(resolve, t); | ||
}); | ||
} |
28 changes: 28 additions & 0 deletions
28
packages/amplify-provider-awscloudformation/src/aws-utils/aws-amplify-backend.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import AWS from 'aws-sdk'; | ||
import aws from './aws'; | ||
import { loadConfiguration } from '../configuration-manager'; | ||
import { $TSContext } from 'amplify-cli-core'; | ||
|
||
export class AmplifyBackend { | ||
private static instance: AmplifyBackend; | ||
private readonly context: $TSContext; | ||
public amplifyBackend: AWS.AmplifyBackend; | ||
|
||
static async getInstance(context: $TSContext, options = {}): Promise<AmplifyBackend> { | ||
if (!AmplifyBackend.instance) { | ||
let cred = {}; | ||
try { | ||
cred = await loadConfiguration(context); | ||
} catch (e) { | ||
// ignore missing config | ||
} | ||
AmplifyBackend.instance = new AmplifyBackend(context, cred, options); | ||
} | ||
return AmplifyBackend.instance; | ||
} | ||
|
||
private constructor(context: $TSContext, creds, options = {}) { | ||
this.context = context; | ||
this.amplifyBackend = new aws.AmplifyBackend({ ...creds, ...options }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters