generator-pyhipster
Version:
Python (Flask) + Angular/React/Vue in one handy generator
937 lines (840 loc) • 35 kB
JavaScript
/**
* Copyright 2013-2022 the original author or authors from the JHipster project.
*
* This file is part of the JHipster project, see https://www.jhipster.tech/
* for more information.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable consistent-return */
const os = require('os');
const shelljs = require('shelljs');
const fs = require('fs');
const chalk = require('chalk');
const _ = require('lodash');
const BaseBlueprintGenerator = require('../generator-base-blueprint');
const { INITIALIZING_PRIORITY, PROMPTING_PRIORITY, CONFIGURING_PRIORITY, LOADING_PRIORITY, WRITING_PRIORITY, END_PRIORITY } =
require('../../lib/constants/priorities.cjs').compat;
const { GENERATOR_GAE } = require('../generator-list');
const statistics = require('../statistics');
const dockerPrompts = require('../docker-prompts');
const constants = require('../generator-constants');
const cacheProviders = require('../../jdl/jhipster/cache-types');
const { MEMCACHED } = require('../../jdl/jhipster/cache-types');
const { GATEWAY, MICROSERVICE, MONOLITH } = require('../../jdl/jhipster/application-types');
const { MARIADB, MYSQL, POSTGRESQL } = require('../../jdl/jhipster/database-types');
const { MAVEN, GRADLE } = require('../../jdl/jhipster/build-tool-types');
const NO_CACHE_PROVIDER = cacheProviders.NO;
module.exports = class extends BaseBlueprintGenerator {
async _postConstruct() {
if (!this.fromBlueprint) {
await this.composeWithBlueprints(GENERATOR_GAE);
}
}
_initializing() {
return {
sayHello() {
this.log(chalk.bold('Welcome to Google App Engine Generator'));
},
checkInstallation() {
if (this.abort) return;
const done = this.async();
shelljs.exec('gcloud version', { silent: true }, (code, stdout, err) => {
if (err && code !== 0) {
this.log.error("You don't have the Cloud SDK (gcloud) installed. \nDownload it from https://cloud.google.com/sdk/install");
this.abort = true;
}
done();
});
},
checkAppEngineJavaComponent() {
if (this.abort) return;
const done = this.async();
const component = 'app-engine-java';
shelljs.exec(
'gcloud components list --quiet --filter="Status=Installed OR Status=\\"Update Available\\"" --format="value(id)"',
{ silent: true },
(err, stdout, srderr) => {
if (_.includes(stdout, component)) {
done();
} else {
this.log(chalk.bold('\nInstalling App Engine Java SDK'));
this.log(`... Running: gcloud components install ${component} --quiet`);
shelljs.exec(`gcloud components install ${component} --quiet`, { silent: true }, (code, stdout, err) => {
if (err && code !== 0) {
this.log.error(err);
done(
`Installation failed. \nPlease try to install the app-engine-java component manually via; gcloud components install ${component}`
);
}
done();
});
}
}
);
},
loadCommonConfig() {
this.loadAppConfig();
this.loadServerConfig();
this.loadPlatformConfig();
this.loadClientConfig();
},
loadConfig() {
const configuration = this.config;
this.env.options.appPath = configuration.get('appPath') || constants.CLIENT_MAIN_SRC_DIR;
this.mainClass = this.getMainClassName();
this.cacheProvider = this.cacheProvider || NO_CACHE_PROVIDER;
this.enableHibernateCache = this.enableHibernateCache && ![NO_CACHE_PROVIDER, MEMCACHED].includes(this.cacheProvider);
this.frontendAppName = this.getFrontendAppName();
this.gcpProjectId = configuration.get('gcpProjectId');
this.gcpCloudSqlInstanceName = configuration.get('gcpCloudSqlInstanceName');
this.gcpCloudSqlUserName = configuration.get('gcpCloudSqlUserName');
this.gcpCloudSqlDatabaseName = configuration.get('gcpCloudSqlDatabaseName');
this.gaeServiceName = configuration.get('gaeServiceName');
this.gaeLocation = configuration.get('gaeLocation');
this.gaeInstanceClass = configuration.get('gaeInstanceClass');
this.gaeScalingType = configuration.get('gaeScalingType');
this.gaeInstances = configuration.get('gaeInstances');
this.gaeMaxInstances = configuration.get('gaeMaxInstances');
this.gaeMinInstances = configuration.get('gaeMinInstances');
this.gaeCloudSQLInstanceNeeded = configuration.get('gaeCloudSQLInstanceNeeded');
this.CLIENT_DIST_DIR = this.getResourceBuildDirectoryForBuildTool(this.config.buildTool) + constants.CLIENT_DIST_DIR;
this.dasherizedBaseName = _.kebabCase(this.baseName);
},
};
}
get [INITIALIZING_PRIORITY]() {
if (this.delegateToBlueprint) return {};
return this._initializing();
}
_prompting() {
return {
askForPath() {
if (this.abort) return undefined;
if (this.applicationType !== GATEWAY) return undefined;
const messageAskForPath = 'Enter the root directory where the microservices are located';
const prompts = [
{
type: 'input',
name: 'directoryPath',
message: messageAskForPath,
default: this.directoryPath || '../',
validate: input => {
const path = this.destinationPath(input);
if (shelljs.test('-d', path)) {
const appsFolders = this._getMicroserviceFolders(input);
if (appsFolders.length === 0) {
return `No microservices are found in ${path}`;
}
return true;
}
return `${path} is not a directory or doesn't exist`;
},
},
];
return this.prompt(prompts).then(props => {
this.directoryPath = props.directoryPath;
// Patch the path if there is no trailing "/"
if (!this.directoryPath.endsWith('/')) {
this.log(chalk.yellow(`The path "${this.directoryPath}" does not end with a trailing "/", adding it anyway.`));
this.directoryPath += '/';
}
this.appsFolders = this._getMicroserviceFolders(this.directoryPath);
this.log(chalk.green(`${this.appsFolders.length} applications found at ${this.destinationPath(this.directoryPath)}\n`));
});
},
askForApps() {
if (this.regenerate) return undefined;
if (this.applicationType !== GATEWAY) return undefined;
const messageAskForApps = 'Which microservice applications do you want to include in your configuration?';
const prompts = [
{
type: 'checkbox',
name: 'chosenApps',
message: messageAskForApps,
choices: this.appsFolders,
default: this.defaultAppsFolders,
validate: input => (input.length === 0 ? 'Please choose at least one application' : true),
},
];
return this.prompt(prompts).then(props => {
this.appsFolders = props.chosenApps;
dockerPrompts.loadConfigs.call(this);
});
},
askForProjectId() {
if (this.abort) return;
const done = this.async();
const prompts = [
{
type: 'input',
name: 'gcpProjectId',
message: 'Google Cloud Project ID',
default: this._defaultProjectId(),
validate: input => {
if (input.trim().length === 0) {
return 'Project ID cannot empty';
}
try {
shelljs.exec(`gcloud projects describe ${input}`, { silent: true });
} catch (ex) {
return `Project ID "${chalk.cyan(input.trim())}" does not exist, please create one first!`;
}
return true;
},
},
];
this.prompt(prompts).then(props => {
this.gcpProjectId = props.gcpProjectId.trim();
done();
});
},
askForLocation() {
if (this.abort) return;
const done = this.async();
shelljs.exec(
`gcloud app describe --format="value(locationId)" --project="${this.gcpProjectId}"`,
{ silent: true },
(code, stdout, err) => {
if (err && code !== 0) {
const prompts = [
{
type: 'list',
name: 'gaeLocation',
message: 'In which Google App Engine location do you want to deploy ?',
choices: [
{ value: 'northamerica-northeast1', name: 'northamerica-northeast1 - Montréal' },
{ value: 'us-central', name: 'us-central1 - Iowa' },
{ value: 'us-east1', name: 'us-east1 - South Carolina' },
{ value: 'us-east4', name: 'us-east4 - Northern Virginia' },
{ value: 'us-west2', name: 'us-west2 - Los Angeles' },
{ value: 'us-west3', name: 'us-west3 - Salt Lake City' },
{ value: 'us-west4', name: 'us-west4 - Las Vegas' },
{ value: 'southamerica-east1', name: 'southamerica-east1 - São Paulo' },
{ value: 'europe-west', name: 'europe-west1 - Belgium' },
{ value: 'europe-west2', name: 'europe-west2 - London' },
{ value: 'europe-west3', name: 'europe-west3 - Frankfurt' },
{ value: 'europe-west6', name: 'europe-west6 - Zürich' },
{ value: 'asia-northeast1', name: 'asia-northeast1 - Tokyo' },
{ value: 'asia-northeast2', name: 'asia-northeast2 - Osaka' },
{ value: 'asia-northeast3', name: 'asia-northeast3 - Seoul' },
{ value: 'asia-south1', name: 'asia-south1 - Mumbai' },
{ value: 'asia-east2', name: 'asia-east2 - Hong Kong' },
{ value: 'asia-southeast2', name: 'asia-southeast2 - Jakarta' },
{ value: 'australia-southeast1', name: 'australia-southeast1 - Sydney' },
],
default: this.gaeLocation ? this.gaeLocation : 0,
},
];
this.prompt(prompts).then(props => {
this.gaeLocation = props.gaeLocation;
this.gaeLocationExists = false;
done();
});
} else {
this.gaeLocationExists = true;
this.gaeLocation = stdout.trim();
this.log(`This project already has an App Engine location set, using location "${chalk.cyan(this.gaeLocation)}"`);
done();
}
}
);
},
askForServiceName() {
if (this.abort) return;
const done = this.async();
try {
shelljs.exec(`gcloud app services describe default --project="${this.gcpProjectId}"`, { silent: true });
this.defaultServiceExists = true;
} catch (ex) {
this.defaultServiceExists = false;
}
const prompts = [
{
type: 'list',
name: 'gaeServiceName',
message: 'Google App Engine Service Name',
choices: this._defaultServiceNameChoices(this.defaultServiceExists),
default: this.gaeServiceName ? this.gaeServiceName : 0,
},
];
this.prompt(prompts).then(props => {
this.gaeServiceName = props.gaeServiceName;
done();
});
},
askForInstanceClass() {
if (this.abort) return;
const done = this.async();
const prompts = [
{
type: 'list',
name: 'gaeInstanceClass',
message: 'Google App Engine Instance Class',
choices: [
{ value: 'F1', name: 'F1 - 600MHz, 256MB, Automatic Scaling' },
{ value: 'F2', name: 'F2 - 1.2GHz, 512MB, Automatic Scaling' },
{ value: 'F4', name: 'F4 - 2.4GHz, 1GB, Automatic Scaling' },
{ value: 'F4_1G', name: 'F4_1G - 2.4GHz, 2GB, Automatic' },
{ value: 'B1', name: 'B1 - 600MHz, 256MB, Basic or Manual Scaling' },
{ value: 'B2', name: 'B2 - 1.2GHz, 512MB, Basic or Manual Scaling' },
{ value: 'B4', name: 'B4 - 2.4GHz, 1GB, Basic or Manual Scaling' },
{ value: 'B4_1G', name: 'B4_1G - 2.4GHz, 2GB, Basic or Manual Scaling' },
{ value: 'B8', name: 'B8 - 4.8GHz, 2GB, Basic or Manual Scaling' },
],
default: this.gaeInstanceClass ? this.gaeInstanceClass : 0,
},
];
this.prompt(prompts).then(props => {
this.gaeInstanceClass = props.gaeInstanceClass;
done();
});
},
askForScalingType() {
if (this.abort) return;
const done = this.async();
if (this.gaeInstanceClass.startsWith('F')) {
this.log(
`Instance Class "${chalk.cyan(this.gaeInstanceClass)}" can only be automatically scaled. Setting scaling type to automatic.`
);
this.gaeScalingType = 'automatic';
done();
} else {
const prompts = [
{
type: 'list',
name: 'gaeScalingType',
message: 'Basic or Manual Scaling',
choices: ['basic', 'manual'],
default: this.gaeScalingType ? this.gaeScalingType : 0,
},
];
this.prompt(prompts).then(props => {
this.gaeScalingType = props.gaeScalingType;
done();
});
}
},
askForInstances() {
if (this.abort) return;
const done = this.async();
const prompts = [];
if (this.gaeScalingType === 'manual') {
prompts.push({
type: 'input',
name: 'gaeInstances',
message: 'How many instances to run ?',
default: this.gaeInstances ? this.gaeInstances : '1',
validate: input => {
if (input.length === 0) {
return 'Instances cannot be empty';
}
const n = Math.floor(Number(input));
if (n === Infinity || String(n) !== input || n <= 0) {
return 'Please enter an integer greater than 0';
}
return true;
},
});
}
if (this.gaeScalingType === 'automatic') {
prompts.push({
type: 'input',
name: 'gaeMinInstances',
message: 'How many instances minimum ?',
default: this.gaeMinInstances ? this.gaeMinInstances : '0',
validate: input => {
if (input.length === 0) {
return 'Minimum Instances cannot be empty';
}
const n = Math.floor(Number(input));
if (n === Infinity || String(n) !== input || n < 0) {
return 'Please enter an integer >= 0';
}
return true;
},
});
}
if (this.gaeScalingType === 'automatic' || this.gaeScalingType === 'basic') {
prompts.push({
type: 'input',
name: 'gaeMaxInstances',
message: 'How many instances max (0 for unlimited) ?',
default: this.gaeMaxInstances ? this.gaeMaxInstances : '0',
validate: input => {
if (input.length === 0) {
return 'Max Instances cannot be empty';
}
const n = Math.floor(Number(input));
if (n === Infinity || String(n) !== input || n < 0) {
return 'Please enter an integer >= 0';
}
return true;
},
});
}
this.prompt(prompts).then(props => {
this.gaeInstances = props.gaeInstances;
this.gaeMaxInstances = props.gaeMaxInstances;
this.gaeMinInstances = props.gaeMinInstances;
done();
});
},
askIfCloudSqlIsNeeded() {
if (this.abort) return;
const done = this.async();
const prompts = [];
prompts.push({
type: 'input',
name: 'gaeCloudSQLInstanceNeeded',
message: 'Use a Cloud SQL instance (Y/N) ?',
default: this.gaeCloudSQLInstanceNeeded ? this.gaeCloudSQLInstanceNeeded : 'Y',
validate: input => {
if (input !== 'Y' && input !== 'N') {
return 'Input should be Y or N';
}
return true;
},
});
this.prompt(prompts).then(props => {
this.gaeCloudSQLInstanceNeeded = props.gaeCloudSQLInstanceNeeded;
done();
});
},
askForCloudSqlInstance() {
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.abort) return;
if (this.prodDatabaseType !== MYSQL && this.prodDatabaseType !== MARIADB && this.prodDatabaseType !== POSTGRESQL) return;
const done = this.async();
const cloudSqlInstances = [{ value: '', name: 'New Cloud SQL Instance' }];
shelljs.exec(
`gcloud sql instances list --format="value[separator=':'](project,region,name)" --project="${this.gcpProjectId}"`,
(code, stdout, err) => {
if (err && code !== 0) {
this.log.error(err);
} else {
_.forEach(stdout.toString().split(os.EOL), instance => {
if (!instance) return;
cloudSqlInstances.push({ value: instance.trim(), name: instance });
});
}
const prompts = [
{
type: 'list',
name: 'gcpCloudSqlInstanceName',
message: 'Google Cloud SQL Instance Name',
choices: cloudSqlInstances,
default: this.gcpCloudSqlInstanceName ? this.gcpCloudSqlInstanceName : 0,
},
];
this.prompt(prompts).then(props => {
this.gcpCloudSqlInstanceName = props.gcpCloudSqlInstanceName;
this.gcpCloudSqlInstanceNameExists = true;
done();
});
}
);
},
promptForCloudSqlInstanceNameIfNeeded() {
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.abort) return;
if (this.gcpCloudSqlInstanceName) return;
const done = this.async();
const prompts = [
{
type: 'input',
name: 'gcpCloudSqlInstanceName',
message: 'Google Cloud SQL Instance Name',
default: this.gcpCloudSqlInstanceName ? this.gcpCloudSqlInstanceName : this.baseName,
},
];
this.prompt(prompts).then(props => {
this.gcpCloudSqlInstanceName = props.gcpCloudSqlInstanceName;
this.gcpCloudSqlInstanceNameExists = false;
done();
});
},
askForCloudSqlLogin() {
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.abort) return;
if (!this.gcpCloudSqlInstanceName) return;
const done = this.async();
const prompts = [
{
type: 'input',
name: 'gcpCloudSqlUserName',
message: 'Google Cloud SQL User Name',
default: this.gcpCloudSqlUserName ? this.gcpCloudSqlUserName : 'root',
validate: input => {
if (input.length === 0) {
return 'User Name cannot empty';
}
return true;
},
},
{
type: 'password',
name: 'gcpCloudSqlPassword',
message: 'Google Cloud SQL Password',
default: this.gcpCloudSqlPassword ? this.gcpCloudSqlPassword : '',
},
];
this.prompt(prompts).then(props => {
this.gcpCloudSqlUserName = props.gcpCloudSqlUserName;
this.gcpCloudSqlPassword = props.gcpCloudSqlPassword;
done();
});
},
askForCloudSqlDatabaseName() {
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.abort) return;
if (!this.gcpCloudSqlInstanceNameExists) return;
const done = this.async();
const cloudSqlDatabases = [{ value: '', name: 'New Database' }];
const name = this.gcpCloudSqlInstanceName.split(':')[2];
shelljs.exec(
`gcloud sql databases list -i ${name} --format="value(name)" --project="${this.gcpProjectId}"`,
{ silent: true },
(code, stdout, err) => {
if (err && code !== 0) {
this.log.error(err);
} else {
_.forEach(stdout.toString().split(os.EOL), database => {
if (!database) return;
cloudSqlDatabases.push({ value: database, name: database });
});
}
const prompts = [
{
type: 'list',
name: 'gcpCloudSqlDatabaseName',
message: 'Google Cloud SQL Database Name',
choices: cloudSqlDatabases,
default: this.gcpCloudSqlDatabaseName ? this.gcpCloudSqlDatabaseName : 0,
},
];
this.prompt(prompts).then(props => {
this.gcpCloudSqlDatabaseName = props.gcpCloudSqlDatabaseName;
this.gcpCloudSqlDatabaseNameExists = true;
done();
});
}
);
},
promptForCloudSqlDatabaseNameIfNeeded() {
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.abort) return;
if (this.gcpCloudSqlInstanceName !== 'new' && this.gcpCloudSqlDatabaseName) return;
const done = this.async();
const prompts = [
{
type: 'input',
name: 'gcpCloudSqlDatabaseName',
message: 'Google Cloud SQL Database Name',
default: this.gcpCloudSqlDatabaseName ? this.gcpCloudSqlDatabaseName : this.baseName,
},
];
this.prompt(prompts).then(props => {
this.gcpCloudSqlDatabaseName = props.gcpCloudSqlDatabaseName;
this.gcpCloudSqlDatabaseNameExists = false;
done();
});
},
};
}
get [PROMPTING_PRIORITY]() {
if (this.delegateToBlueprint) return {};
return this._prompting();
}
_configuring() {
return {
insight() {
statistics.sendSubGenEvent('generator', GENERATOR_GAE);
},
configureProject() {
if (this.abort) return;
const done = this.async();
if (!this.gaeLocationExists) {
this.log(chalk.bold(`Configuring Google App Engine Location "${chalk.cyan(this.gaeLocation)}"`));
shelljs.exec(
`gcloud app create --region="${this.gaeLocation}" --project="${this.gcpProjectId}"`,
{ silent: true },
(code, stdout, err) => {
if (err && code !== 0) {
this.log.error(err);
this.abort = true;
}
done();
}
);
} else {
done();
}
},
createCloudSqlInstance() {
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.abort) return;
if (!this.gcpCloudSqlInstanceName) return;
if (this.gcpCloudSqlInstanceNameExists) return;
const done = this.async();
this.log(chalk.bold('\nCreating New Cloud SQL Instance'));
const name = this.gcpCloudSqlInstanceName;
// for mysql keep default options, set specific option for pg
const dbVersionFlag = this.prodDatabaseType === 'postgresql' ? ' --database-version="POSTGRES_9_6" --tier="db-g1-small"' : '';
let gaeCloudSqlLocation = this.gaeLocation;
if (gaeCloudSqlLocation === 'us-central') {
gaeCloudSqlLocation = 'us-central1';
} else if (gaeCloudSqlLocation === 'europe-west') {
gaeCloudSqlLocation = 'europe-west1';
}
const cmd = `gcloud sql instances create "${name}" --region='${gaeCloudSqlLocation}' --project=${this.gcpProjectId}${dbVersionFlag}`;
this.log(chalk.bold(`\n... Running: ${cmd}`));
shelljs.exec(cmd, { silent: true }, (code, stdout, err) => {
if (err && code !== 0) {
this.abort = true;
this.log.error(err);
}
const cloudSQLInstanceName = shelljs.exec(
`gcloud sql instances describe ${name} --format="value(connectionName)" --project="${this.gcpProjectId}"`,
{ silent: true }
);
this.gcpCloudSqlInstanceName = cloudSQLInstanceName.trim();
done();
});
},
createCloudSqlLogin() {
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.abort) return;
if (!this.gcpCloudSqlInstanceName) return;
const done = this.async();
this.log(chalk.bold('\nConfiguring Cloud SQL Login'));
const name = this.gcpCloudSqlInstanceName.split(':')[2];
shelljs.exec(
`gcloud sql users list -i jhipster --format="value(name)" --project="${this.gcpProjectId}"`,
{ silent: true },
(code, stdout, err) => {
if (_.includes(stdout, this.gcpCloudSqlUserName)) {
this.log(chalk.bold(`... User "${chalk.cyan(this.gcpCloudSqlUserName)}" already exists`));
const cmd = `gcloud sql users set-password "${this.gcpCloudSqlUserName}" -i "${name}" --host="%" --project="${this.gcpProjectId}" --password="..."`;
this.log(chalk.bold(`... To set its password, run: ${cmd}`));
done();
} else {
const cmd = `gcloud sql users create "${this.gcpCloudSqlUserName}" -i "${name}" --host="%" --password="${this.gcpCloudSqlPassword}" --project="${this.gcpProjectId}"`;
this.log(chalk.bold(`... Running: ${cmd}`));
shelljs.exec(cmd, { silent: true }, (code, stdout, err) => {
if (err && code !== 0) {
this.log.error(err);
}
done();
});
}
}
);
},
createCloudSqlDatabase() {
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.abort) return;
if (!this.gcpCloudSqlInstanceName) return;
if (this.gcpCloudSqlDatabaseNameExists) return;
const done = this.async();
const name = this.gcpCloudSqlInstanceName.split(':')[2];
this.log(chalk.bold(`\nCreating Database ${chalk.cyan(this.gcpCloudSqlDatabaseName)}`));
const cmd = `gcloud sql databases create "${this.gcpCloudSqlDatabaseName}" --charset=utf8 -i "${name}" --project="${this.gcpProjectId}"`;
this.log(chalk.bold(`... Running: ${cmd}`));
shelljs.exec(cmd, { silent: true }, (code, stdout, err) => {
if (err && code !== 0) {
this.log.error(err);
}
done();
});
},
saveConfig() {
this.config.set({
gcpProjectId: this.gcpProjectId,
gcpCloudSqlInstanceName: this.gcpCloudSqlInstanceName,
gcpCloudSqlUserName: this.gcpCloudSqlUserName,
gcpCloudSqlDatabaseName: this.gcpCloudSqlDatabaseName,
gaeServiceName: this.gaeServiceName,
gaeLocation: this.gaeLocation,
gaeInstanceClass: this.gaeInstanceClass,
gaeScalingType: this.gaeScalingType,
gaeInstances: this.gaeInstances,
gaeMinInstances: this.gaeMinInstances,
gaeMaxInstances: this.gaeMaxInstances,
gaeCloudSQLInstanceNeeded: this.gaeCloudSQLInstanceNeeded,
});
},
};
}
get [CONFIGURING_PRIORITY]() {
if (this.delegateToBlueprint) return {};
return this._configuring();
}
_loading() {
return {
loadSharedConfig() {
this.loadDerivedAppConfig();
},
};
}
get [LOADING_PRIORITY]() {
if (this.delegateToBlueprint) return {};
return this._loading();
}
_writing() {
return {
copyFiles() {
if (this.abort) return;
this.log(chalk.bold('\nCreating Google App Engine deployment files'));
this.template('app.yaml.ejs', `${constants.MAIN_DIR}/appengine/app.yaml`);
if (this.applicationType === GATEWAY) {
this.template('dispatch.yaml.ejs', `${constants.MAIN_DIR}/appengine/dispatch.yaml`);
}
this.template('application-prod-gae.yml.ejs', `${constants.SERVER_MAIN_RES_DIR}/config/application-prod-gae.yml`);
if (this.buildTool === 'gradle') {
this.template('gae.gradle.ejs', 'gradle/gae.gradle');
}
},
addDependencies() {
if (this.abort) return;
if (this.buildTool === MAVEN) {
this.addMavenDependency('org.springframework.boot.experimental', 'spring-boot-thin-layout', '1.0.23.RELEASE');
}
if (this.gaeCloudSQLInstanceNeeded === 'N') return;
if (this.prodDatabaseType === MYSQL || this.prodDatabaseType === MARIADB) {
if (this.buildTool === MAVEN) {
this.addMavenDependency('com.google.cloud.sql', 'mysql-socket-factory', '1.0.8');
} else if (this.buildTool === GRADLE) {
this.addGradleDependency('compile', 'com.google.cloud.sql', 'mysql-socket-factory', '1.0.8');
}
}
if (this.prodDatabaseType === POSTGRESQL) {
if (this.buildTool === MAVEN) {
this.addMavenDependency('com.google.cloud.sql', 'postgres-socket-factory', '1.0.12');
} else if (this.buildTool === GRADLE) {
this.addGradleDependency('compile', 'com.google.cloud.sql', 'postgres-socket-factory', '1.0.12');
}
}
},
addGradlePlugin() {
if (this.abort) return;
if (this.buildTool === GRADLE) {
this.addGradlePlugin('com.google.cloud.tools', 'appengine-gradle-plugin', '2.2.0');
this.addGradlePlugin('org.springframework.boot.experimental', 'spring-boot-thin-gradle-plugin', '1.0.13.RELEASE');
this.applyFromGradleScript('gradle/gae');
}
},
addMavenPlugin() {
if (this.abort) return;
if (this.buildTool === MAVEN) {
this.render('pom-plugin.xml.ejs', rendered => {
this.addMavenPlugin('com.google.cloud.tools', 'appengine-maven-plugin', '2.2.0', rendered.trim());
});
this.render('pom-profile.xml.ejs', rendered => {
this.addMavenProfile('prod-gae', ` ${rendered.trim()}`);
});
this.render('pom-gae-build-profile.xml.ejs', rendered => {
this.addMavenProfile('gae', ` ${rendered.trim()}`);
});
}
},
};
}
get [WRITING_PRIORITY]() {
if (this.delegateToBlueprint) return {};
return this._writing();
}
_end() {
return {
productionBuild() {
if (this.abort) return;
// Until issue; https://github.com/GoogleCloudPlatform/app-gradle-plugin/issues/376 is fixed we shall disable .gcloudignore
this.log(
chalk.bold(
'Due to a Bug in GCloud SDK you will need to disable the generation of .gcloudignore file before deploying using: "gcloud config set gcloudignore/enabled false". For more info refer: https://github.com/GoogleCloudPlatform/app-gradle-plugin/issues/376'
)
);
if (this.buildTool === MAVEN) {
this.log(chalk.bold('Deploy to App Engine: ./mvnw package appengine:deploy -DskipTests -Pgae,prod,prod-gae'));
} else if (this.buildTool === 'gradle') {
this.log(chalk.bold('Deploy to App Engine: ./gradlew appengineDeploy -Pgae -Pprod-gae'));
}
/*
if (this.gcpSkipBuild || this.gcpDeployType === 'git') {
this.log(chalk.bold('\nSkipping build'));
return;
}
const done = this.async();
this.log(chalk.bold('\nBuilding application'));
const child = this.buildApplication(this.buildTool, 'prod', (err) => {
if (err) {
this.abort = true;
this.log.error(err);
}
done();
});
this.buildCmd = child.buildCmd;
child.stdout.on('data', (data) => {
process.stdout.write(data.toString());
}); */
},
};
}
get [END_PRIORITY]() {
if (this.delegateToBlueprint) return {};
return this._end();
}
_defaultProjectId() {
if (this.abort) return null;
if (this.gcpProjectId) {
return this.gcpProjectId;
}
try {
const projectId = shelljs.exec('gcloud config get-value core/project --quiet', { silent: true }).stdout;
return projectId.trim();
} catch (ex) {
this.log.error('Unable to determine the default Google Cloud Project ID');
return undefined;
}
}
_defaultServiceNameChoices(defaultServiceExists) {
if (this.applicationType === MONOLITH) {
return defaultServiceExists ? ['default', _.kebabCase(this.baseName)] : ['default'];
}
if (this.applicationType === GATEWAY) {
return ['default'];
}
return [_.kebabCase(this.baseName)];
}
_getMicroserviceFolders(input) {
const destinationPath = this.destinationPath(input);
const files = shelljs.ls('-l', destinationPath);
const appsFolders = [];
files.forEach(file => {
if (file.isDirectory()) {
if (fs.existsSync(`${destinationPath}/${file.name}/.yo-rc.json`)) {
try {
const fileData = this.fs.readJSON(`${destinationPath}/${file.name}/.yo-rc.json`);
if (fileData['generator-jhipster'].applicationType === MICROSERVICE) {
appsFolders.push(file.name.match(/([^/]*)\/*$/)[1]);
}
} catch (err) {
this.log(chalk.red(`${file}: this .yo-rc.json can't be read`));
this.debug('Error:', err);
}
}
}
});
return appsFolders;
}
};