From ba31c167f5d3894f507b7b3854f1371f4217ddab Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Thu, 13 Jul 2017 20:02:58 +0530 Subject: [PATCH 1/5] K8s configMap refresh --- .../service/CloudConfigRefreshService.java | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/main/java/io/github/jhipster/registry/service/CloudConfigRefreshService.java diff --git a/src/main/java/io/github/jhipster/registry/service/CloudConfigRefreshService.java b/src/main/java/io/github/jhipster/registry/service/CloudConfigRefreshService.java new file mode 100644 index 000000000..fda1edb45 --- /dev/null +++ b/src/main/java/io/github/jhipster/registry/service/CloudConfigRefreshService.java @@ -0,0 +1,181 @@ +package io.github.jhipster.registry.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.refresh.ContextRefresher; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.io.File; +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.stream.Collectors; + +import static com.sun.nio.file.SensitivityWatchEventModifier.HIGH; +import static io.github.jhipster.config.JHipsterConstants.SPRING_PROFILE_K8S; +import static java.nio.file.FileVisitOption.FOLLOW_LINKS; +import static java.nio.file.FileVisitResult.CONTINUE; +import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; + +/** + * Kubernetes (K8s) cloud config refresher service + */ +@Service +@Profile(SPRING_PROFILE_K8S) +public class CloudConfigRefreshService { + + private final Logger log = LoggerFactory.getLogger(CloudConfigRefreshService.class); + + private final ContextRefresher refresher; + + private final String configPath; + + private ScheduledExecutorService taskExecutor; + + /** + * Constructor + * + * @param refresher ContextRefresher + * @param configPath String + */ + public CloudConfigRefreshService(ContextRefresher refresher, @Value("${k8s.config.path}") String configPath) { + this.refresher = refresher; + this.configPath = configPath; + } + + /** + * Creates a daemon thread when {@link #getConfigPath configPath} is specified through the environment + * variable {@code k8s.config.path}. Daemon thread will execute the watcher service asynchronously. + */ + @PostConstruct + public void configMapWatcher() { + if (getConfigPath() != null && !getConfigPath().isEmpty()) { + taskExecutor = Executors.newSingleThreadScheduledExecutor( + job -> { + Thread thread = new Thread(job, "CloudConfigMapRefresher"); + thread.setDaemon(true); + return thread; + } + ); + taskExecutor.execute(() -> { + try { + configMapRefreshContext(); + } catch (IOException | InterruptedException ex) { + log.error("Unable to refresh K8s ConfigMap", ex); + } + }); + } else { + log.error("ConfigMap directory path not specified. Specify value for the environment variable k8s.config.path"); + } + } + + /** + * {@code WatchService} object to monitor K8s configMap path. Mounted configMap path will be recursively + * registered with the {@code WatchService} instance to get notified for interested events. + * + * @throws IOException + * @throws InterruptedException + */ + public void configMapRefreshContext() throws IOException, InterruptedException { + List fileList = new ArrayList(); + List hashList = new ArrayList(); + WatchService watcherService = FileSystems.getDefault().newWatchService(); + Path dirPath = Paths.get(getConfigPath()); + Files.walkFileTree(dirPath, new HashSet() { + { + add(FOLLOW_LINKS); + } + }, 2, new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + log.debug("Registering" + dir + " in watcher service"); + dir.register(watcherService, new WatchEvent.Kind[]{ENTRY_MODIFY}, HIGH); + return CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { + File file = path.toFile(); + if (isValidConfigFile(file.getName().toLowerCase())) { + log.debug("Adding file: " + file.getAbsolutePath()); + fileList.add(file); + hashList.add(getHashValue(file)); + } + return CONTINUE; + } + }); + while (true) { + WatchKey key = watcherService.take(); + List> events = key.pollEvents(); + if (!events.isEmpty()) { + if (log.isDebugEnabled()) { + events.forEach(event -> log.debug("Event detected: " + event.kind().name() + ", Updated File: " + event.context())); + } + Collection activeList = fileList.stream().map(entry -> getHashValue(entry)).collect(Collectors.toList()); + if (!hashList.containsAll(activeList)) { + log.debug("File system updated. Hashed content matching failed"); + hashList.clear(); + hashList.addAll(activeList); + refresher.refresh(); + log.debug("@Refreshscope context refreshed for ConfigMap update"); + } else { + // do nothing + log.debug("Hashed content unchanged. Ignore and continue"); + } + if (!key.reset()) { + log.error("Unable to reset the watcher service. Try restarting the running instance"); + break; + } + } else { + // do nothing + log.debug("Event list is empty. Ignore and continue."); + } + } + } + + @PreDestroy + public void destroy() { + if (taskExecutor != null) { + taskExecutor.shutdown(); + } + } + + /** + * Generates hash value + * @param file File + * @return hasCode int + */ + private int getHashValue(File file) { + return (37 * 21 + (file.getAbsolutePath().hashCode() + (int) (file.length() ^ (file.length() >>> 32)) + + (int) (file.lastModified() ^ (file.lastModified() >>> 32)))); + } + + /** + * Checks for valid file extension + * + * @param name String - file name + * @return boolean + */ + private boolean isValidConfigFile(String name) { + return name.endsWith(".yml") || name.endsWith(".yaml") || name.endsWith(".properties"); + } + + /** + * Returns config path + * + * @return configPath String + */ + public String getConfigPath() { + return configPath; + } +} From 937fff2fffb57f54b80239a0b47a15fcd5f630d5 Mon Sep 17 00:00:00 2001 From: Srinivasa Vasu Date: Wed, 23 Aug 2017 09:14:56 +0530 Subject: [PATCH 2/5] upgrade to 1.1.9 lib version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6bf2d1e1f..6cf09c6c7 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 1.3 0.7.9 1.8 - 1.1.7 + 1.1.9 0.7.0 4.9 1.3.0 From 363deb9ea72ec95a6b54f2068128732a9d4c021c Mon Sep 17 00:00:00 2001 From: Pierre Besson Date: Thu, 24 Aug 2017 17:44:38 +0200 Subject: [PATCH 3/5] add docker hub badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2512f34b1..b14dbcaf4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # JHipster Registry -[![Build Status][travis-image]][travis-url] +[![Build Status][travis-image]][travis-url] [![Docker Pulls](https://img.shields.io/docker/pulls/jhipster/jhipster-registry.svg)](https://hub.docker.com/r/jhipster/jhipster-registry/) This is the [JHipster](http://jhipster.github.io/) registry service, based on [Spring Cloud Netflix](http://cloud.spring.io/spring-cloud-netflix/), [Eureka](https://github.com/Netflix/eureka) and [Spring Cloud Config](http://cloud.spring.io/spring-cloud-config/). From 9cd1f224afb6bf035c8e782a02a690a8f974cbc0 Mon Sep 17 00:00:00 2001 From: Julien Dubois Date: Tue, 5 Sep 2017 11:19:38 +0200 Subject: [PATCH 4/5] Add contributing guidelines and templates --- .github/ISSUE_TEMPLATE.md | 39 ++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 6 ++ CONTRIBUTING.md | 126 +++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..8f6fbe899 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,39 @@ + + +##### **Overview of the issue** + + + +##### **Motivation for or Use Case** + + + +##### **Reproduce the error** + + + +##### **Related issues** + + + +##### **Suggest a Fix** + + + +##### **JHipster Registry Version(s)** + + + +##### **Browsers and Operating System** + + + +- [ ] Checking this box is mandatory (this is just to show you read everything) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..830d9e6f5 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,6 @@ +- Please make sure the below checklist is followed for Pull Requests. + +- [ ] [Travis tests](https://travis-ci.org/jhipster/jhipster-registry/pull_requests) are green +- [ ] Tests are added where necessary +- [ ] Documentation is added/updated where necessary +- [ ] Coding Rules & Commit Guidelines as per our [CONTRIBUTING.md document](https://github.com/jhipster/jhipster-registry/blob/master/CONTRIBUTING.md) are followed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..2926dc4bf --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,126 @@ +# Contributing to the JHipster Registry + +Are you ready to contribute to the JHipster Registry? We'd love to have you on board, and we will help you as much as we can. + +Our contributing guidelines are basically the same as [the JHipster generator contributing guidelines](https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md). + +Here are the guidelines we'd like you to follow so that we can be of more help: + + - [Questions and help](#question) + - [Issues and Bugs](#issue) + - [Feature Requests](#feature) + - [Submission Guidelines](#submit) + - [Generator development setup](#setup) + - [Coding Rules](#rules) + - [Git Commit Guidelines](#commit) + +## Questions and help +This is the JHipster bug tracker, and it is used for [Issues and Bugs](#issue) and for [Feature Requests](#feature). It is **not** a help desk or a support forum. + +If you have a question on using JHipster, or if you need help with your JHipster project, please [read our help page](http://www.jhipster.tech/help/) and use the [JHipster tag on StackOverflow](http://stackoverflow.com/tags/jhipster) or join our [Gitter.im chat room](https://gitter.im/jhipster/generator-jhipster). + +## Issues and Bugs +If you find a bug in the source code or a mistake in the documentation, you can help us by [submitting a ticket](https://opensource.guide/how-to-contribute/#opening-an-issue) to our [GitHub issues](https://github.com/jhipster/jhipster-registry/issues). Even better, you can submit a Pull Request to our [JHipster Registry project](https://github.com/jhipster/jhipster-registry) or to our [Documentation project](https://github.com/jhipster/jhipster.github.io). + +**Please see the Submission Guidelines below**. + +## Feature Requests +You can request a new feature by submitting a ticket to our [GitHub issues](https://github.com/jhipster/jhipster-registry/issues). If you +would like to implement a new feature then consider what kind of change it is: + +* **Major Changes** that you wish to contribute to the project should be discussed first. Please open a ticket which clearly states that it is a feature request in the title and explain clearly what you want to achieve in the description, and the JHipster team will discuss with you what should be done in that ticket. You can then start working on a Pull Request. +* **Small Changes** can be proposed without any discussion. Open up a ticket which clearly states that it is a feature request in the title. Explain your change in the description, and you can propose a Pull Request straight away. + +## Submission Guidelines + +### [Submitting an Issue](https://opensource.guide/how-to-contribute/#opening-an-issue) +Before you submit your issue search the [archive](https://github.com/jhipster/jhipster-registry/issues?utf8=%E2%9C%93&q=is%3Aissue), maybe your question was already answered. + +If your issue appears to be a bug, and has not been reported, open a new issue. +Help us to maximize the effort we can spend fixing issues and adding new +features, by not reporting duplicate issues. Providing the following information will increase the +chances of your issue being dealt with quickly: + +* **Overview of the issue** - if an error is being thrown a stack trace helps +* **Motivation for or Use Case** - explain why this is a bug for you +* **Reproduce the error** - an unambiguous set of steps to reproduce the error. If you have a JavaScript error, maybe you can provide a live example with + [JSFiddle](http://jsfiddle.net/)? +* **Related issues** - has a similar issue been reported before? +* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be + causing the problem (line of code or commit) +* **JHipster Registry Version(s)** - is it a regression? +* **Browsers and Operating System** - is this a problem with all browsers or only IE8? + +Click [here](https://github.com/jhipster/jhipster-registry/issues/new) to open a bug issue with a pre-filled template. For feature requests and enquiries you can use [this template][feature-template]. + +Issues opened without any of these info will be **closed** without any explanation. + +### [Submitting a Pull Request](https://opensource.guide/how-to-contribute/#opening-a-pull-request) +Before you submit your pull request consider the following guideline: + +* Search [GitHub](https://github.com/jhipster/jhipster-registry/pulls?utf8=%E2%9C%93&q=is%3Apr) for an open or closed Pull Request + that relates to your submission. + +## Coding Rules +To ensure consistency throughout the source code, keep these rules in mind as you are working: + +* All features or bug fixes **must be tested** by one or more tests. +* All files must follow the [.editorconfig file](http://editorconfig.org/) located at the root of the JHipster Registry project. Please note that generated projects use the same `.editorconfig` file, so that both the generator and the generated projects share the same configuration. +* Java files **must be** formatted using [Intellij IDEA's code style](http://confluence.jetbrains.com/display/IntelliJIDEA/Code+Style+and+Formatting). Please note that JHipster committers have a free Intellij IDEA Ultimate Edition for developing the project. +* Generators JavaScript files **must follow** the eslint configuration defined at the project root, which is based on [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript). +* Web apps JavaScript files **must follow** [Google's JavaScript Style Guide](https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml). +* AngularJS files **must follow** [John Papa's Angular 1 style guide](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md). +* Angular 2+ Typescript files **must follow** [Official Angular style guide](https://angular.io/styleguide). + +Please ensure to run `npm run lint` and `npm test` on the project root before submitting a pull request. You can also run `npm run lint-fix` to fix some of the lint issues automatically. + +## Git Commit Guidelines + +We have rules over how our git commit messages must be formatted. Please ensure to [squash](https://help.github.com/articles/about-git-rebase/#commands-available-while-rebasing) unnecessary commits so that your commit history is clean. + +### Commit Message Format +Each commit message consists of a **header**, a **body** and a **footer**. + +``` +
+ + + +