From 8a62d7a4fdaf255ce62bbf3e5cd58ff901afe393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Delbrayelle?= Date: Sat, 6 Jun 2020 10:33:44 +0200 Subject: [PATCH] fix: --skip-prompts option (#74) closes #59 --- README.md | 8 +++++++ generators/app/index.js | 49 +++++++++++++++++---------------------- generators/app/prompts.js | 24 ++++++++++++------- generators/constants.js | 12 ++++++---- test/app.spec.js | 37 ++++++++++++++++++++++++++++- 5 files changed, 88 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 27df25b..26e2177 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,14 @@ This describes how to use basically this module with a JHipster generated projec 5. In the same folder, then run `yo jhipster-kafka` 6. You can choose to add a consumer and/or a producer for an given entity name (identified by its domain class name in the package `domain` of your JHipster application, where entities are generated by `jhipster entity` or JDL Studio based file through `jhipster import-jdl file_name.jh`) +## Skip prompts + +You can use `yo jhipster-kafka --skip-prompts` to use the default prompts values to generate: + +- a minimal `kafka` configuration in `application.yml` files with only a `bootstrap.servers` +- a `akhq.yml` docker-compose file to run AKHQ (see below) +- a `GenericConsumer.java` that you extend to create your own consumers + ## Test consumers and producers You can use your producer (`*Producer.java`) in other layers like resources or services by instancing it and using its `send` method (which is asynchronous). diff --git a/generators/app/index.js b/generators/app/index.js index 0c56aec..1f37c1b 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -21,7 +21,7 @@ module.exports = class extends BaseGenerator { this.isFirstGeneration = false; // This adds support for a `--skip-prompts` flag this.option('skip-prompts', { - desc: 'Generate pre-existing configuration', + desc: 'Generate configuration with default values', type: Boolean, defaults: false }); @@ -73,18 +73,6 @@ module.exports = class extends BaseGenerator { } prompting() { - // To generate a consumer and a producer for CI tests - if (this.options['skip-prompts']) { - this.log('Skipping prompts...'); - this.props.generationType = constants.BIGBANG_MODE; - this.props.components.push(constants.CONSUMER_COMPONENT, constants.PRODUCER_COMPONENT); - // DocumentBankAccount entity is generated for tests purpose - // in the main generator (see: 11-generate-entities.sh). - this.props.entities.push('DocumentBankAccount'); - this.props.autoOffsetResetPolicies = constants.EARLIEST_OFFSET; - return; - } - prompts.askForOperations(this); } @@ -142,12 +130,17 @@ module.exports = class extends BaseGenerator { this.log(`dockerComposeFormatVersion=${this.dockerComposeFormatVersion}`); this.log(`dockerAkhq=${this.dockerAkhq}`); - this.log('\n--- variables from questions ---'); - this.log(`\ncomponents=${this.components}`); - this.log(`\nentities=${this.entities}`); - this.log(`\ncomponentsPrefixes=${this.componentsPrefixes}`); - this.log(`\npollingTimeout=${this.pollingTimeout}`); - this.log(`\nautoOffsetResetPolicy=${this.autoOffsetResetPolicy}`); + if (this.options['skip-prompts']) { + this.log('\n------'); + this.log('Skipping prompts...'); + } else { + this.log('\n--- variables from questions ---'); + this.log(`\ncomponents=${this.components}`); + this.log(`\nentities=${this.entities}`); + this.log(`\ncomponentsPrefixes=${this.componentsPrefixes}`); + this.log(`\npollingTimeout=${this.pollingTimeout}`); + this.log(`\nautoOffsetResetPolicy=${this.autoOffsetResetPolicy}`); + } this.log('------\n'); this.registerToEntityPostHook(); @@ -241,12 +234,6 @@ module.exports = class extends BaseGenerator { null, null ); - this.template( - 'src/main/java/package/service/kafka/deserializer/DeserializationError.java.ejs', - `${javaDir}service/kafka/deserializer/DeserializationError.java`, - null, - null - ); } if (mustGenerateComponent(entity, constants.PRODUCER_COMPONENT)) { @@ -319,13 +306,19 @@ module.exports = class extends BaseGenerator { shelljs.rm('-rf', `${javaDir}service/kafka/`, `${javaDir}web/rest/kafka/`); } - if (containsComponent(constants.CONSUMER_COMPONENT)) { + if (this.options['skip-prompts'] || containsComponent(constants.CONSUMER_COMPONENT)) { this.template( 'src/main/java/package/service/kafka/GenericConsumer.java.ejs', `${javaDir}service/kafka/GenericConsumer.java`, null, null ); + this.template( + 'src/main/java/package/service/kafka/deserializer/DeserializationError.java.ejs', + `${javaDir}service/kafka/deserializer/DeserializationError.java`, + null, + null + ); } if (containsComponent(constants.CONSUMER_COMPONENT) || containsComponent(constants.PRODUCER_COMPONENT)) { @@ -391,10 +384,10 @@ module.exports = class extends BaseGenerator { } else { // big bang properties writing const kafkaProperties = generateKafkaProperties(true); - this.log(`kafkaProperties=\n\n${kafkaProperties}\n\n`); + this.log(`application.yml (src/main/resources) kafka block will be updated like this:${kafkaProperties}`); const kafkaTestProperties = generateKafkaProperties(false); - this.log(`kafkaTestProperties=\n\n${kafkaTestProperties}\n\n`); + this.log(`application.yml (src/test/resources) kafka block will be updated like this:${kafkaTestProperties}`); const kafkaBlockPattern = /\n+kafka:\n(\s.+\n+)+/g; this.replaceContent(`${resourceDir}config/application.yml`, kafkaBlockPattern, kafkaProperties); diff --git a/generators/app/prompts.js b/generators/app/prompts.js index 3655d1a..06a6186 100644 --- a/generators/app/prompts.js +++ b/generators/app/prompts.js @@ -88,6 +88,7 @@ function entitiesChoices(context) { function askForOperations(context) { const prompts = [ { + when: !context.options['skip-prompts'], type: 'list', name: 'generationType', message: 'Which type of generation do you want?', @@ -100,10 +101,10 @@ function askForOperations(context) { try { context.prompt(prompts).then(props => { context.props.generationType = props.generationType; - if (props.generationType === constants.INCREMENTAL_MODE) { - askForIncrementalOperations(context, done); - } else { + if (!props.generationType || props.generationType === constants.BIGBANG_MODE) { askForBigBangOperations(context, done); + } else if (props.generationType === constants.INCREMENTAL_MODE) { + askForIncrementalOperations(context, done); } }); } catch (e) { @@ -115,6 +116,7 @@ function askForOperations(context) { function askForBigBangOperations(context, done) { const bigbangPrompt = [ { + when: !context.options['skip-prompts'], type: 'checkbox', name: 'components', message: 'Which Kafka components would you like to generate?', @@ -129,7 +131,7 @@ function askForBigBangOperations(context, done) { name: 'entities', message: 'For which entity (class name)?', choices: entitiesChoices(context), - default: [], + default: constants.NO_ENTITY, validate: input => (_.isEmpty(input) ? 'You have to choose at least one option' : true) }, { @@ -150,7 +152,7 @@ function askForBigBangOperations(context, done) { type: 'number', name: 'pollingTimeout', message: 'What is the consumer polling timeout (in ms)?', - default: '10000', + default: constants.DEFAULT_POLLING_TIMEOUT, validate: input => (isNaN(input) ? 'Please enter a number' : true) }, { @@ -164,12 +166,18 @@ function askForBigBangOperations(context, done) { } ]; + if (context.options['skip-prompts']) { + context.props = _.merge(context.props, bigbangPrompt.map(prompt => prompt.default)); + done(); + return; + } + context.prompt(bigbangPrompt).then(answers => { if (answers.componentPrefix) { context.props.componentsPrefixes.push(answers.componentPrefix); } + context.props = _.merge(context.props, answers); - // To access props later use this.props.someOption; done(); }); } @@ -196,7 +204,7 @@ function askForIncrementalOperations(context, done) { name: 'currentEntity', message: 'For which entity (class name)?', choices: [...getConcernedEntities(previousConfiguration(context))], - default: [] + default: constants.NO_ENTITY }, { when: response => response.currentEntity === constants.NO_ENTITY, @@ -313,7 +321,7 @@ function askForUnitaryEntityOperations(context, done) { type: 'number', name: 'pollingTimeout', message: 'What is the consumer polling timeout (in ms)?', - default: '10000' + default: constants.DEFAULT_POLLING_TIMEOUT }, { when: response => diff --git a/generators/constants.js b/generators/constants.js index bdadfb5..b0a50bd 100644 --- a/generators/constants.js +++ b/generators/constants.js @@ -28,6 +28,7 @@ const NO_ENTITY = 'no_entity'; const EARLIEST_OFFSET = 'earliest'; const LATEST_OFFSET = 'latest'; const NONE_OFFSET = 'none'; +const DEFAULT_POLLING_TIMEOUT = '10000'; const JSON_EXTENSION = '.json'; const EMPTY_STRING = ''; @@ -35,16 +36,17 @@ const constants = { JHIPSTER_CONFIG_DIR, MODULES_HOOK_FILE, MODULE_NAME, - CONSUMER_COMPONENT, - PRODUCER_COMPONENT, BIGBANG_MODE, INCREMENTAL_MODE, + CONSUMER_COMPONENT, + PRODUCER_COMPONENT, NO_ENTITY, - JSON_EXTENSION, - EMPTY_STRING, EARLIEST_OFFSET, LATEST_OFFSET, - NONE_OFFSET + NONE_OFFSET, + DEFAULT_POLLING_TIMEOUT, + JSON_EXTENSION, + EMPTY_STRING }; module.exports = constants; diff --git a/test/app.spec.js b/test/app.spec.js index 5df0cc2..3c1c2f9 100644 --- a/test/app.spec.js +++ b/test/app.spec.js @@ -33,6 +33,40 @@ describe('JHipster generator kafka', () => { }); }); + describe('with --force --skip-prompts options', () => { + before(done => { + helpers + .run(path.join(__dirname, '../generators/app')) + .inTmpDir(dir => { + fse.copySync(path.join(__dirname, '../test/templates/message-broker-with-entities-1st-call'), dir); + }) + .withOptions({ force: true, skipPrompts: true }) + .on('end', done); + }); + + it('should generate generic consumer and akhq.yml', () => { + const expectedFiles = [ + `${jhipsterConstants.SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/kafka/GenericConsumer.java`, + `${jhipsterConstants.SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/kafka/deserializer/DeserializationError.java`, + `${jhipsterConstants.MAIN_DIR}docker/akhq.yml` + ]; + + assert.file(expectedFiles); + }); + + it('should update application.yml', () => { + assert.fileContent( + `${jhipsterConstants.SERVER_MAIN_RES_DIR}config/application.yml`, + /bootstrap.servers: \${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}/ + ); + + assert.fileContent( + `${jhipsterConstants.SERVER_TEST_RES_DIR}config/application.yml`, + /bootstrap.servers: \${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}/ + ); + }); + }); + describe('with the big bang mode', () => { describe('with a consumer and a producer for a single entity', () => { before(done => { @@ -720,7 +754,8 @@ function itGeneratesBasicConfigurationWithConsumerProducerWithAnEntity(entityNam `${jhipsterConstants.SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/kafka/deserializer/${entityName}Deserializer.java`, `${jhipsterConstants.SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/kafka/producer/${entityName}Producer.java`, `${jhipsterConstants.SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/kafka/serializer/${entityName}Serializer.java`, - `${jhipsterConstants.SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/kafka/${entityName}KafkaResource.java` + `${jhipsterConstants.SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/kafka/${entityName}KafkaResource.java`, + `${jhipsterConstants.MAIN_DIR}docker/akhq.yml` ]; assert.file(expectedFiles); });