diff --git a/pom.xml b/pom.xml index 9c6cda1..0aff825 100644 --- a/pom.xml +++ b/pom.xml @@ -106,7 +106,7 @@ applicationinsights-core ${azure.applicationinsights.version} - + diff --git a/src/main/java/com/microsoft/azure/springcloudplayground/generator/ProjectGenerator.java b/src/main/java/com/microsoft/azure/springcloudplayground/generator/ProjectGenerator.java index 396a895..4c44864 100644 --- a/src/main/java/com/microsoft/azure/springcloudplayground/generator/ProjectGenerator.java +++ b/src/main/java/com/microsoft/azure/springcloudplayground/generator/ProjectGenerator.java @@ -89,7 +89,7 @@ private void writeKubernetesFile(File dir, ProjectRequest request){ writeText(new File(dir, KUBERNETES_FILE), templateRenderer.process(Paths.get(DOCKER_PATH, KUBERNETES_FILE).toString(), model)); } - private void generateDockerStructure(@NonNull File rootDir, @NonNull String baseDir, Map modulesModel, ProjectRequest request) { + private void generateDockerStructure(@NonNull File rootDir, @NonNull String baseDir, Map modulesModel, ProjectRequest request) { final File dockerDir = Paths.get(rootDir.getPath(),baseDir, "docker").toFile(); final String template = "docker"; final String dockerComposeName = "docker-compose.yml"; @@ -99,6 +99,8 @@ private void generateDockerStructure(@NonNull File rootDir, @NonNull String base dockerDir.mkdir(); + request.getModules().forEach(m -> modulesModel.put(m.getName() + "-" + "port", m.getPort())); + writeText(new File(dockerDir, dockerComposeName), templateRenderer.process(Paths.get(template, dockerComposeName).toString(), modulesModel)); writeText(new File(dockerDir, runBash), templateRenderer.process(Paths.get(template, runBash).toString(), null)); writeText(new File(dockerDir, runCmd), templateRenderer.process(Paths.get(template, runCmd).toString(), null)); @@ -116,16 +118,15 @@ public File generateProjectStructure(ProjectRequest request) { try { Map model = resolveModel(request); File rootDir = generateProjectStructure(request, model); + final Map modulesModel = new HashMap<>(); - final Map modulesModel = new HashMap<>(); for(ProjectRequest subModule: request.getModules()){ - generateProjectModuleStructure(subModule, resolveModel(subModule), - new File(rootDir, request.getBaseDir()), request); + final File subModuleDir = new File(rootDir, request.getBaseDir()); + generateProjectModuleStructure(subModule, resolveModel(subModule), subModuleDir, request); modulesModel.put(subModule.getName(), Boolean.TRUE); } generateDockerStructure(rootDir, request.getBaseDir(), modulesModel, request); - //publishProjectGeneratedEvent(request); return rootDir; } @@ -135,6 +136,23 @@ public File generateProjectStructure(ProjectRequest request) { } } + private void servicesPortsUpdate(@NonNull ProjectRequest request) { + Assert.isNull(request.getParent(), "should be parent project."); + + final Set set = new HashSet<>(); + final Map ports = request.getServicesPorts(); + final List services = request.getServices(); + + services.stream().filter(s -> ports.get(s) != null && ports.get(s) >= 1024 && ports.get(s) <= 65535) + .forEach(s -> set.add(ports.get(s))); + + if (set.size() < services.size()) { + ports.forEach((key, value) -> ports.put(key, ServiceMetadata.portMap.get(key))); + } + + request.getModules().forEach(m -> m.setPort(ports.get(m.getName()))); + } + /** * Generate a project structure for the specified {@link ProjectRequest} and resolved * model. @@ -142,8 +160,7 @@ public File generateProjectStructure(ProjectRequest request) { * @param model the source model * @return the generated project structure */ - protected File generateProjectStructure(ProjectRequest request, - Map model) { + protected File generateProjectStructure(ProjectRequest request, Map model) { File rootDir; try { rootDir = File.createTempFile("tmp", "", getTemporaryDirectory()); @@ -171,6 +188,7 @@ protected File generateProjectStructure(ProjectRequest request, } generateGitIgnore(dir, request); + servicesPortsUpdate(request); return rootDir; } @@ -193,16 +211,17 @@ protected File generateProjectModuleStructure(ProjectRequest request, writeText(new File(dir, "settings.gradle"), settings); } else { + // Write Dockerfile to module final String dockerFileName = "Dockerfile"; final String exposePortVariable = "EXPOSE_PORT"; final String dockerTemplateDir = "docker"; final Map portModel = new HashMap<>(); - portModel.put(exposePortVariable, ServiceMetadata.portMap.get(request.getName())); + final String path = Paths.get(dockerTemplateDir, dockerFileName).toString(); + + portModel.put(exposePortVariable, request.getPort()); + writeText(new File(dir, dockerFileName), templateRenderer.process(path, portModel)); - // Write Dockerfile to module log.info("Writing Dockerfile to module " + request.getName()); - writeText(new File(dir, dockerFileName), - templateRenderer.process(Paths.get(dockerTemplateDir, dockerFileName).toString(), portModel)); // Write pom file String pom = new String(doGenerateMavenPom(model, "module-pom.xml")); @@ -216,13 +235,10 @@ protected File generateProjectModuleStructure(ProjectRequest request, request.getPackageName().replace(".", "/")); src.mkdirs(); if(request.getName().equalsIgnoreCase("cloud-hystrix-dashboard")){ - write(new File(src, applicationName + "." + language), - "HystrixDashboardApplication." + language, model); - write(new File(src, "MockStreamServlet.java"), - "MockStreamServlet.java", model); + write(new File(src, applicationName + "." + language), "HystrixDashboardApplication." + language, model); + write(new File(src, "MockStreamServlet.java"), "MockStreamServlet.java", model); } else { - write(new File(src, applicationName + "." + language), - "Application." + language, model); + write(new File(src, applicationName + "." + language), "Application." + language, model); } if (request.getDependencies().contains("web")) { @@ -299,7 +315,7 @@ private void writePropertiesFile(ProjectRequest request, File resourceDir, Proje model.put("services", azureServices); } else if(!ModulePropertiesResolver.isInfraModule(moduleName)){ model.put("applicationName", module.getName()); - model.put("port", getPort(module.getName())); + model.put("port", request.getPort()); } String content = templateRenderer.process(templateFile, model); @@ -320,10 +336,6 @@ private void writeBootstrapYaml(ProjectRequest request, File resourceDir) { writeText(new File(resourceDir, "bootstrap.yml"), content); } - private int getPort(String serviceName) { - return ServiceMetadata.portMap.get(serviceName); - } - /** * Create a distribution file for the specified project structure directory and * extension. diff --git a/src/main/java/com/microsoft/azure/springcloudplayground/generator/ProjectRequest.java b/src/main/java/com/microsoft/azure/springcloudplayground/generator/ProjectRequest.java index 1afa001..b4f033d 100644 --- a/src/main/java/com/microsoft/azure/springcloudplayground/generator/ProjectRequest.java +++ b/src/main/java/com/microsoft/azure/springcloudplayground/generator/ProjectRequest.java @@ -6,16 +6,16 @@ import com.microsoft.azure.springcloudplayground.util.Version; import com.microsoft.azure.springcloudplayground.util.VersionProperty; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.Setter; import org.springframework.beans.BeanWrapperImpl; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; -@NoArgsConstructor public class ProjectRequest extends BasicProjectRequest { /** @@ -44,6 +44,13 @@ public class ProjectRequest extends BasicProjectRequest { @Setter private List facets = new ArrayList<>(); + @Getter + private Map servicesPorts; + + @Getter + @Setter + private Integer port; + private List services = new ArrayList<>(); private final Map subModules = new HashMap<>(); @@ -52,6 +59,10 @@ public class ProjectRequest extends BasicProjectRequest { @Setter private String build; + public ProjectRequest() { + servicesPorts = new HashMap<>(); + } + public ProjectRequest(ProjectRequest parentProject) { super(parentProject); this.resolvedDependencies = parentProject.resolvedDependencies; @@ -59,6 +70,12 @@ public ProjectRequest(ProjectRequest parentProject) { this.build = parentProject.build; } + public Integer getServicePort(@NonNull String serviceName) { + Assert.isNull(this.getParent(), "should be parent module of Request"); + + return this.servicesPorts.get(serviceName); + } + public void removeDependency(String id) { if (this.resolvedDependencies != null) { Predicate filter = d -> d.getId().equals(id); @@ -149,8 +166,7 @@ public void resolve(GeneratorMetadata metadata) { } if (!StringUtils.hasText(getApplicationName())) { - setApplicationName( - metadata.getConfiguration().generateApplicationName(getName())); + setApplicationName(metadata.getConfiguration().generateApplicationName(getName())); } setPackageName(metadata.getConfiguration().cleanPackageName(getPackageName(), metadata.getPackageName().getContent())); @@ -203,8 +219,7 @@ private void resolveBom(GeneratorMetadata metadata, String bomId, if (!this.boms.containsKey(bomId)) { BillOfMaterials bom = metadata.getConfiguration().getEnv().getBoms() .get(bomId).resolve(requestedVersion); - bom.getAdditionalBoms() - .forEach((id) -> resolveBom(metadata, id, requestedVersion)); + bom.getAdditionalBoms().forEach((id) -> resolveBom(metadata, id, requestedVersion)); this.boms.put(bomId, bom); } } @@ -265,4 +280,24 @@ public Collection getModules() { public void addModule(ProjectRequest module) { this.subModules.put(module.getName(), module); } + + public void setCloudConfigServerPort(@NonNull Integer port) { + this.servicesPorts.put("cloud-config-server", port); + } + + public void setCloudGatewayPort(@NonNull Integer port) { + this.servicesPorts.put("cloud-gateway", port); + } + + public void setCloudEurekaServerPort(@NonNull Integer port) { + this.servicesPorts.put("cloud-eureka-server", port); + } + + public void setCloudHystrixDashboardPort(@NonNull Integer port) { + this.servicesPorts.put("cloud-hystrix-dashboard", port); + } + + public void setAzureServiceBusPort(@NonNull Integer port) { + this.servicesPorts.put("azure-service-bus", port); + } } diff --git a/src/main/java/com/microsoft/azure/springcloudplayground/service/ServiceModule.java b/src/main/java/com/microsoft/azure/springcloudplayground/service/ServiceModule.java index 5884e65..e503388 100644 --- a/src/main/java/com/microsoft/azure/springcloudplayground/service/ServiceModule.java +++ b/src/main/java/com/microsoft/azure/springcloudplayground/service/ServiceModule.java @@ -2,8 +2,15 @@ import com.microsoft.azure.springcloudplayground.metadata.Describable; import com.microsoft.azure.springcloudplayground.metadata.MetadataElement; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.NonNull; import lombok.Setter; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; @NoArgsConstructor public class ServiceModule extends MetadataElement implements Describable { @@ -11,19 +18,32 @@ public class ServiceModule extends MetadataElement implements Describable { @Setter private String description; + @Getter + private String portId; + @Override public String getDescription() { return this.description; } - public ServiceModule(ServiceModule module) { - super(module); - this.description = module.description; - } - public ServiceModule(String id, String name, String description) { super(id, name); this.description = description; + this.portId = toPortId(id); + } + + private String toPortId(@NonNull String id) { + final List tails = new ArrayList<>(Arrays.asList(id.split("-"))); + final String head = tails.remove(0); + final String tail = String.join("", tails.stream().map(StringUtils::capitalize).toArray(String[]::new)); + + return head + tail + "Port"; + } + + @Override + public void setId(@NonNull String id) { + this.id = id; + this.portId = toPortId(id); } @Override @@ -31,14 +51,4 @@ public String toString() { return "ServiceModule{" + "id='" + getId() + '\'' + ", name='" + getName() + '\'' + ", description='" + this.getDescription() + '\'' + '}'; } - - public static ServiceModule withId(String id, String name, String description) { - ServiceModule module = new ServiceModule(); - - module.setId(id); - module.setName(name); - module.setDescription(description); - - return module; - } } diff --git a/src/main/resources/static/css/customize.css b/src/main/resources/static/css/customize.css index 43dc845..68209f3 100644 --- a/src/main/resources/static/css/customize.css +++ b/src/main/resources/static/css/customize.css @@ -34,7 +34,7 @@ padding-left: 20px; } -.module-checkbox input { +.module-checkbox input:first-child { margin-left: -20px; } diff --git a/src/main/resources/templates/docker/docker-compose.yml b/src/main/resources/templates/docker/docker-compose.yml index fa43a0e..3b833ac 100644 --- a/src/main/resources/templates/docker/docker-compose.yml +++ b/src/main/resources/templates/docker/docker-compose.yml @@ -4,9 +4,9 @@ services: config-server: image: "demo/cloud-config-server" ports: - - "8888:8888" + - "{{cloud-config-server-port}}:{{cloud-config-server-port}}" healthcheck: - test: ["CMD", "curl", "-f", "http://config-server:8888/gateway-server.yml"] + test: ["CMD", "curl", "-f", "http://config-server:{{cloud-config-server-port}}/gateway-server.yml"] interval: 5s retries: 20 {{/cloud-config-server}} @@ -14,14 +14,14 @@ services: eureka-server: image: "demo/cloud-eureka-server" ports: - - "8761:8761" + - "{{cloud-eureka-server-port}}:{{cloud-eureka-server-port}}" links: - config-server depends_on: config-server: condition: service_healthy healthcheck: - test: ["CMD", "curl", "-f", "http://eureka-server:8761"] + test: ["CMD", "curl", "-f", "http://eureka-server:{{cloud-eureka-server-port}}"] interval: 5s retries: 20 {{/cloud-eureka-server}} @@ -29,7 +29,7 @@ services: service-bus-server: image: "demo/azure-service-bus" ports: - - "8081:8081" + - "{{azure-service-bus-port}}:{{azure-service-bus-port}}" links: - eureka-server - config-server @@ -37,7 +37,7 @@ services: eureka-server: condition: service_healthy healthcheck: - test: ["CMD", "curl", "-f", "http://service-bus-server:8081/azure-service-bus/actuator/health"] + test: ["CMD", "curl", "-f", "http://service-bus-server:{{azure-service-bus-port}}/azure-service-bus/actuator/health"] interval: 5s retries: 20 {{/azure-service-bus}} @@ -45,7 +45,7 @@ services: hystrix-server: image: "demo/cloud-hystrix-dashboard" ports: - - "7979:7979" + - "{{cloud-hystrix-dashboard-port}}:{{cloud-hystrix-dashboard-port}}" links: - eureka-server - config-server @@ -60,9 +60,9 @@ services: - eureka-server - config-server ports: - - "9999:9999" + - "{{cloud-gateway-port}}:{{cloud-gateway-port}}" healthcheck: - test: ["CMD", "curl", "-f", "http://gateway-server:8080/actuator/health"] + test: ["CMD", "curl", "-f", "http://gateway-server:{{cloud-gateway-port}}/actuator/health"] interval: 5s retries: 20 {{/cloud-gateway}} diff --git a/src/main/resources/templates/home.mustache b/src/main/resources/templates/home.mustache index 35fdd88..f93ee6e 100644 --- a/src/main/resources/templates/home.mustache +++ b/src/main/resources/templates/home.mustache @@ -122,6 +122,7 @@ {{name}} + {{#description}}{{.}}{{/description}}
{{#description}}{{.}}{{/description}}