params = new LinkedMultiValueMap<>();
+ params.add("emailsubject", emailData.getEmailSubject());
+ params.add("emailcontent", emailData.getEmailBody());
+ params.add("emailaddress", emailData.getEmailAddress1());
+ params.add("emailaddress", emailData.getEmailAddress2());
+ params.add("emaillocale", emailData.getEmailLocale());
+ mockMvc.perform(MockMvcRequestBuilders.get("/email/requestparameters")
+ .params(params))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("en-US")));
+ }
+
+ @Test
+ public void whenCallSessionAttributes_thenReturnEmailData() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/email/sessionattributes"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("Good morning !")));
+ }
+
+ @Test
+ public void whenCallServletContext_thenReturnEmailData() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/email/servletcontext"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("jhon.doe@example.com")));
+ }
+
+ @Test
+ public void whenCallBeanData_thenReturnEmailData() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/email/beandata"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("jhon.doe@example.com")));
+ }
+
+}
diff --git a/spring-thymeleaf-3/README.md b/spring-thymeleaf-3/README.md
new file mode 100644
index 0000000000..a8e234b067
--- /dev/null
+++ b/spring-thymeleaf-3/README.md
@@ -0,0 +1,6 @@
+## Spring Thymeleaf 3
+
+This module contains articles about Spring with Thymeleaf
+
+## Relevant Articles:
+- [Add CSS and JS to Thymeleaf](https://www.baeldung.com/spring-thymeleaf-css-js)
diff --git a/spring-thymeleaf-3/pom.xml b/spring-thymeleaf-3/pom.xml
new file mode 100644
index 0000000000..7677e50d79
--- /dev/null
+++ b/spring-thymeleaf-3/pom.xml
@@ -0,0 +1,78 @@
+
+
+ 4.0.0
+ spring-thymeleaf-3
+ spring-thymeleaf-3
+ war
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ com.baeldung.thymeleaf.cssandjs.CssAndJsApplication
+ JAR
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+ org.apache.tomcat.maven
+ tomcat7-maven-plugin
+ ${tomcat7-maven-plugin.version}
+
+
+ tomcat-run
+
+ exec-war-only
+
+ package
+
+ /
+ false
+ webapp.jar
+ utf-8
+
+
+
+
+
+ spring-thymeleaf-3
+
+
+
+ 1.8
+ 1.8
+ 2.2
+
+
+
diff --git a/spring-boot-modules/spring-boot-client/src/main/java/org/baeldung/boot/Application.java b/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/Application.java
similarity index 50%
rename from spring-boot-modules/spring-boot-client/src/main/java/org/baeldung/boot/Application.java
rename to spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/Application.java
index c1b6558b26..2ccca82497 100644
--- a/spring-boot-modules/spring-boot-client/src/main/java/org/baeldung/boot/Application.java
+++ b/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/Application.java
@@ -1,14 +1,11 @@
-package org.baeldung.boot;
+package com.baeldung.thymeleaf;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class Application {
- private static ApplicationContext applicationContext;
-
public static void main(String[] args) {
- applicationContext = SpringApplication.run(Application.class, args);
+ SpringApplication.run(Application.class, args);
}
}
diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsApplication.java b/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsApplication.java
new file mode 100644
index 0000000000..fc6c142b8b
--- /dev/null
+++ b/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsApplication.java
@@ -0,0 +1,11 @@
+package com.baeldung.thymeleaf.cssandjs;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CssAndJsApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(CssAndJsApplication.class, args);
+ }
+}
diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsController.java b/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsController.java
new file mode 100644
index 0000000000..b56a7b468e
--- /dev/null
+++ b/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsController.java
@@ -0,0 +1,15 @@
+package com.baeldung.thymeleaf.cssandjs;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class CssAndJsController {
+
+ @GetMapping("/styled-page")
+ public String getStyledPage(Model model) {
+ model.addAttribute("name", "Baeldung Reader");
+ return "cssandjs/styledPage";
+ }
+}
diff --git a/spring-thymeleaf-3/src/main/resources/static/js/cssandjs/actions.js b/spring-thymeleaf-3/src/main/resources/static/js/cssandjs/actions.js
new file mode 100644
index 0000000000..e192e6358e
--- /dev/null
+++ b/spring-thymeleaf-3/src/main/resources/static/js/cssandjs/actions.js
@@ -0,0 +1,7 @@
+function showAlert() {
+ alert("The button was clicked!");
+}
+
+function showName(name) {
+ alert("Here's the name: " + name);
+}
\ No newline at end of file
diff --git a/spring-thymeleaf-3/src/main/resources/static/styles/cssandjs/main.css b/spring-thymeleaf-3/src/main/resources/static/styles/cssandjs/main.css
new file mode 100644
index 0000000000..1f57b4616a
--- /dev/null
+++ b/spring-thymeleaf-3/src/main/resources/static/styles/cssandjs/main.css
@@ -0,0 +1,18 @@
+h2 {
+ font-family: sans-serif;
+ font-size: 1.5em;
+ text-transform: uppercase;
+}
+
+strong {
+ font-weight: 700;
+ background-color: yellow;
+}
+
+p {
+ font-family: sans-serif;
+}
+
+label {
+ font-weight: 600;
+}
\ No newline at end of file
diff --git a/spring-thymeleaf-3/src/main/resources/templates/cssandjs/styledPage.html b/spring-thymeleaf-3/src/main/resources/templates/cssandjs/styledPage.html
new file mode 100644
index 0000000000..12e4fc9227
--- /dev/null
+++ b/spring-thymeleaf-3/src/main/resources/templates/cssandjs/styledPage.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Add CSS and JS to Thymeleaf
+
+
+
+
+
+ Carefully Styled Heading
+
+ This is text on which we want to apply very special styling.
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/ApplicationIntegrationTest.java b/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/ApplicationIntegrationTest.java
new file mode 100644
index 0000000000..b7cfa140f0
--- /dev/null
+++ b/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/ApplicationIntegrationTest.java
@@ -0,0 +1,13 @@
+package com.baeldung.thymeleaf;
+
+import org.junit.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+public class ApplicationIntegrationTest {
+
+ @Test
+ public void contextLoads() {
+
+ }
+}
diff --git a/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/cssandjs/CssAndJsControllerIntegrationTest.java b/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/cssandjs/CssAndJsControllerIntegrationTest.java
new file mode 100644
index 0000000000..365608bd2a
--- /dev/null
+++ b/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/cssandjs/CssAndJsControllerIntegrationTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.thymeleaf.cssandjs;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
+@ContextConfiguration(classes = CssAndJsApplication.class)
+public class CssAndJsControllerIntegrationTest {
+ @Autowired
+ private WebApplicationContext context;
+
+ private MockMvc mockMvc;
+
+ @Before
+ public void setup() {
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
+ }
+
+ @Test
+ public void whenCalledGetStyledPage_thenReturnContent() throws Exception {
+ this.mockMvc.perform(MockMvcRequestBuilders.get("/styled-page"))
+ .andExpect(status().isOk())
+ .andExpect(view().name("cssandjs/styledPage"))
+ .andExpect(content().string(containsString("Carefully Styled Heading")));
+ }
+}
diff --git a/terraform/best-practices/README.md b/terraform/best-practices/README.md
new file mode 100644
index 0000000000..fd488b1afb
--- /dev/null
+++ b/terraform/best-practices/README.md
@@ -0,0 +1,10 @@
+# Terraform Sample Code
+
+This folder contains Terraform project samples that illustrates topics covered in the
+"Best practices when using Terraform" article. Setup instructions are available in each sample's folder.
+
+List of available samples:
+
+ * k8s-basic: "Hello world" project that just connects to a Kubernetes cluster and create a new namespace.
+ * ec2-basic: "Hello world" project that creates a single EC2 instance
+ * k8s-modules: A more elaborate sample that creates a simple set of services in a Kubernetes cluster
diff --git a/terraform/best-practices/ec2-simple/.gitignore b/terraform/best-practices/ec2-simple/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/ec2-simple/SETUP.md b/terraform/best-practices/ec2-simple/SETUP.md
new file mode 100644
index 0000000000..3f906b6933
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/SETUP.md
@@ -0,0 +1,23 @@
+# EC2 Basic Sample
+
+This Terraform sample project creates a single EC2 instance in the configured region.
+
+IMPORTANT NOTICE: In order to run this sample you must have an active AWS Account. As you probably know, creating resources on AWS
+may result in additional charges in your bill. We recommend creating a test account to run this test as you can then use AWS's free tier
+to play around. When finished, ALWAYS REMEMBER TO DESTROY YOUR RESOURCES !!!
+
+# Setup instructions
+
+1. Make sure you have a working AWS environment. Use a simple command such as _aws ec2 describe-instances_ and check its output.
+ If you get a list of existing EC2 instances, you're good to go. Otherwise, please refer to AWS documentation in order to setup your CLI.
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _aws ec2 describe-instances_. The output should list the newly creates EC2 instance
+6. Run _terraform destroy_ to remove the previously creates namespace.
+
diff --git a/terraform/best-practices/ec2-simple/main.tf b/terraform/best-practices/ec2-simple/main.tf
new file mode 100644
index 0000000000..57fb9d1757
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/main.tf
@@ -0,0 +1,33 @@
+#
+# Resource definitions
+#
+
+data "aws_ami" "apache" {
+ filter {
+ name = "name"
+ values = [var.ami_name]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+
+ owners = [var.ami_owner]
+
+ most_recent = true
+}
+
+resource "aws_instance" "web" {
+ ami = data.aws_ami.apache.id
+ instance_type = "t2.micro"
+ subnet_id = aws_subnet.frontend.id
+}
+resource "aws_subnet" "frontend" {
+ vpc_id = aws_vpc.apps.id
+ cidr_block = "10.0.1.0/24"
+}
+
+resource "aws_vpc" "apps" {
+ cidr_block = "10.0.0.0/16"
+}
diff --git a/terraform/best-practices/ec2-simple/providers.tf b/terraform/best-practices/ec2-simple/providers.tf
new file mode 100644
index 0000000000..fa5826b067
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/providers.tf
@@ -0,0 +1,6 @@
+#
+# Providers definitions
+#
+provider "aws" {
+ version = "~> 2.53"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/ec2-simple/variables.tf b/terraform/best-practices/ec2-simple/variables.tf
new file mode 100644
index 0000000000..2a7fddcd33
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/variables.tf
@@ -0,0 +1,15 @@
+#
+# Variables
+#
+
+variable "ami_name" {
+ type = string
+ description = "AMI name to use for our EC2 instance. Defaults to Ubuntu 18.04 (Bionic)"
+ default = "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-*"
+}
+
+variable "ami_owner" {
+ type = string
+ description = "AMI Owner ID to use for our EC2 instance. Defaults to 099720109477 (Canonical)"
+ default = "099720109477"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/.gitignore b/terraform/best-practices/k8s-basic/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/k8s-basic/SETUP.md b/terraform/best-practices/k8s-basic/SETUP.md
new file mode 100644
index 0000000000..35e690d88e
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/SETUP.md
@@ -0,0 +1,14 @@
+# Setup instructions
+
+1. Make sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output.
+ If you get a list of nodes that contains at least one _ready_ module, you're good to go
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _kubectl get namespaces_. The output should now have a new "hello-terraform" namespace.
+6. Run _terraform destroy_ to remove the previously creates namespace.
diff --git a/terraform/best-practices/k8s-basic/main.tf b/terraform/best-practices/k8s-basic/main.tf
new file mode 100644
index 0000000000..5eb3749930
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/main.tf
@@ -0,0 +1,12 @@
+#
+# Resource definitions
+#
+
+resource "kubernetes_namespace" "hello" {
+ metadata {
+ labels = {
+ terraform = "true"
+ }
+ name = var.namespace_name
+ }
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/providers.tf b/terraform/best-practices/k8s-basic/providers.tf
new file mode 100644
index 0000000000..385f857a11
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/providers.tf
@@ -0,0 +1,6 @@
+#
+# Providers definitions
+#
+provider "kubernetes" {
+ version = "~> 1.11"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/variables.tf b/terraform/best-practices/k8s-basic/variables.tf
new file mode 100644
index 0000000000..b9217079bf
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/variables.tf
@@ -0,0 +1,9 @@
+#
+# Variables
+#
+
+variable "namespace_name" {
+ type = string
+ description = "Name to use for the created namespace"
+ default = "hello-terraform"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/.gitignore b/terraform/best-practices/k8s-modules/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/k8s-modules/SETUP.md b/terraform/best-practices/k8s-modules/SETUP.md
new file mode 100644
index 0000000000..f00247a293
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/SETUP.md
@@ -0,0 +1,20 @@
+# Kubernetes multimodule sample
+
+This sample deploys two services behind a Kubernetes ingress.
+
+# Setup instructions
+
+1. Make sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output.
+ If you get a list of nodes that contains at least one _ready_ module, you're good to go
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _kubectl get services_. The output should now have a few services.
+6. Run _terraform destroy_ to remove the previously creates namespace.
+
+
diff --git a/terraform/best-practices/k8s-modules/main.tf b/terraform/best-practices/k8s-modules/main.tf
new file mode 100644
index 0000000000..86426b33db
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/main.tf
@@ -0,0 +1,27 @@
+/*
+ * Top-level definitions
+ */
+
+//================================================================== Ingress
+
+module "ingress_www_petshop_com_br" {
+ source = "./modules/ingress/www.petshop.com.br"
+ ingress_host = "www.petshop.com.br"
+}
+
+//================================================================== Deployments
+
+module "SvcCustomer" {
+ source = "./modules/SvcCustomer"
+}
+
+module "SvcFeedback" {
+ source = "./modules/SvcFeedback"
+}
+
+
+
+
+
+
+
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf
new file mode 100644
index 0000000000..1ca0c91545
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf
@@ -0,0 +1,68 @@
+/*
+ * SvcCustomer deployment resources
+ */
+
+resource "kubernetes_deployment" "SvcCustomer" {
+
+ metadata {
+ name = "svccustomer"
+ labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ spec {
+ replicas = 1
+
+ selector {
+ match_labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ template {
+ metadata {
+ labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ spec {
+ image_pull_secrets {
+ name = "docker-config"
+ }
+
+
+ container {
+ image = "inanimate/echo-server"
+ name = "svccustomer-httpd"
+ env {
+ name = "PORT"
+ value = "80"
+ }
+ }
+ }
+ }
+ }
+}
+
+resource "kubernetes_service" "SvcCustomer" {
+ metadata {
+ name = "svccustomer"
+ }
+
+ spec {
+
+ selector = {
+ app = "SvcCustomer"
+ }
+
+ session_affinity = "ClientIP"
+ port {
+ port = 80
+ }
+
+ //type = "LoadBalancer"
+ }
+ }
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf
new file mode 100644
index 0000000000..8a37fdf375
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf
@@ -0,0 +1,3 @@
+/*
+ * SvcCustomer output values
+ */
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf
new file mode 100644
index 0000000000..3dfcfcd264
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf
@@ -0,0 +1,5 @@
+/*
+ * SvcCustomer deployment variables
+ */
+
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf
new file mode 100644
index 0000000000..0f84c9163e
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf
@@ -0,0 +1,69 @@
+/*
+ * SvcFeedback deployment resources
+ */
+
+resource "kubernetes_deployment" "SvcFeedback" {
+
+ metadata {
+ name = "svcfeedback"
+ labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ spec {
+ replicas = 1
+
+ selector {
+ match_labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ template {
+ metadata {
+ labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ spec {
+ image_pull_secrets {
+ name = "docker-config"
+ }
+
+
+ container {
+ image = "inanimate/echo-server"
+ name = "svcfeedback-httpd"
+ env {
+ name = "PORT"
+ value = "80"
+ }
+ }
+
+ }
+ }
+ }
+}
+
+resource "kubernetes_service" "SvcFeedback" {
+ metadata {
+ name = "svcfeedback"
+ }
+
+ spec {
+
+ selector = {
+ app = "SvcFeedback"
+ }
+
+ session_affinity = "ClientIP"
+ port {
+ port = 80
+ }
+
+ //type = "LoadBalancer"
+ }
+ }
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf
new file mode 100644
index 0000000000..e08c17d4b4
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf
@@ -0,0 +1,3 @@
+/*
+ * SvcFeedback output values
+ */
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf
new file mode 100644
index 0000000000..d8076d41a4
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf
@@ -0,0 +1,5 @@
+/*
+ * SvcFeedback deployment variables
+ */
+
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf
new file mode 100644
index 0000000000..0dbda48981
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf
@@ -0,0 +1,41 @@
+/*
+ * Kubernetes Ingress module
+ */
+locals {
+ iname = var.ingress_name == "" ? join("-",["ingress",sha1(uuid())]) : var.ingress_name
+}
+
+resource "kubernetes_ingress" "ingress" {
+ metadata {
+ name = local.iname
+ annotations = map(
+ "nginx.ingress.kubernetes.io/rewrite-target","/"
+ )
+ }
+ spec {
+ rule {
+ http {
+ path {
+ backend {
+ service_name = "svccustomer"
+ service_port = 80
+ }
+ path = "/customers"
+ }
+ path {
+ backend {
+ service_name = "svcfeedback"
+ service_port = 80
+ }
+ path = "/feedback"
+ }
+ }
+ }
+/*
+ tls {
+ secret_name = "tls-secret"
+ }
+*/
+ }
+}
+
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf
new file mode 100644
index 0000000000..e604417b05
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf
@@ -0,0 +1,5 @@
+/*
+ * Output variables
+ */
+
+
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf
new file mode 100644
index 0000000000..9b06128ec5
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf
@@ -0,0 +1,20 @@
+/*
+ * Kubernetes Ingress module
+ */
+
+
+variable "ingress_name" {
+ type = string
+ description = "Ingress name. Defaults to a random name."
+ default = ""
+}
+
+variable "ingress_host" {
+ type = string
+ description = "Ingress hostname"
+ default = "www.petshop.com.br"
+}
+
+
+
+
diff --git a/terraform/best-practices/k8s-modules/provider.tf b/terraform/best-practices/k8s-modules/provider.tf
new file mode 100644
index 0000000000..bb90d66ecf
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/provider.tf
@@ -0,0 +1,13 @@
+#
+# Provider configurations
+# This file will *NOT* be overwriten upon regeneration, so it's safe
+# to add your own customizations
+#
+
+provider "kubernetes" {
+ version = "~> 1.10"
+}
+
+provider "random" {
+ version = "~> 2.2"
+}
\ No newline at end of file
diff --git a/terraform/hello-terraform/.gitignore b/terraform/hello-terraform/.gitignore
new file mode 100644
index 0000000000..452502c50f
--- /dev/null
+++ b/terraform/hello-terraform/.gitignore
@@ -0,0 +1,6 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
+hello.txt
+
diff --git a/terraform/hello-terraform/main.tf b/terraform/hello-terraform/main.tf
new file mode 100644
index 0000000000..d6a726fa36
--- /dev/null
+++ b/terraform/hello-terraform/main.tf
@@ -0,0 +1,7 @@
+provider "local" {
+ version = "~> 1.4"
+}
+resource "local_file" "hello" {
+ content = "Hello, Terraform"
+ filename = "hello.txt"
+}
diff --git a/testing-modules/junit5-annotations/pom.xml b/testing-modules/junit5-annotations/pom.xml
index d0fba4d21b..9e51d0ab55 100644
--- a/testing-modules/junit5-annotations/pom.xml
+++ b/testing-modules/junit5-annotations/pom.xml
@@ -46,12 +46,19 @@
${junit.platform.version}
test