diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b062ee0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.gradle/ +.github/ +.idea/ +.m2/ +.settings +.settings.xml +.settings.gradle +apps/ +.k8s/ +README.md \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 58689d8..135ba63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,13 @@ +FROM cubetiq/openjdk:11u-ubuntu as builder +LABEL maintainer="sombochea@cubetiqs.com" + +WORKDIR /app +RUN apt-get update && apt-get install -y git + +COPY . . + +RUN sh gradlew clean bootJar + FROM cubetiq/calpine-openjdk11:latest LABEL maintainer="sombochea@cubetiqs.com" @@ -8,7 +18,7 @@ WORKDIR /opt/cubetiq VOLUME ["/opt/cubetiq/data"] # Copy build source to container -COPY api/build/libs/*.jar ./api.jar +COPY --from=builder /app/api/build/libs/*.jar ./api.jar ENV APP_DATA_DIR "/opt/cubetiq/data" diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 63065e0..4a7920b 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -32,6 +32,8 @@ springBoot { } dependencies { + implementation("org.springframework.boot:spring-boot-starter-data-mongodb") + // Migrating from SpringFox implementation("org.springdoc:springdoc-openapi-ui:1.5.13") diff --git a/api/src/main/kotlin/com/cubetiqs/web/config/OpenApiDocConfig.kt b/api/src/main/kotlin/com/cubetiqs/web/config/OpenApiDocConfig.kt index 0ae6db9..e1b1094 100644 --- a/api/src/main/kotlin/com/cubetiqs/web/config/OpenApiDocConfig.kt +++ b/api/src/main/kotlin/com/cubetiqs/web/config/OpenApiDocConfig.kt @@ -1,8 +1,10 @@ package com.cubetiqs.web.config import com.cubetiqs.web.property.AppProperties +import io.swagger.v3.oas.annotations.OpenAPIDefinition import io.swagger.v3.oas.annotations.enums.SecuritySchemeType import io.swagger.v3.oas.annotations.security.SecurityScheme +import io.swagger.v3.oas.annotations.servers.Server import io.swagger.v3.oas.models.OpenAPI import io.swagger.v3.oas.models.info.Info import io.swagger.v3.oas.models.info.License @@ -18,11 +20,15 @@ import org.springframework.context.annotation.Configuration scheme = "bearer", bearerFormat = "JWT", ) +@OpenAPIDefinition( + servers = [ + Server(url = "/") + ], +) class OpenApiDocConfig @Autowired constructor( val appProperties: AppProperties, ) { companion object { - private val ADMIN_API_PATH get() = "/admin/**" private val DEFAULT_API_PATH get() = "/**" } @@ -31,19 +37,10 @@ class OpenApiDocConfig @Autowired constructor( return GroupedOpenApi.builder() .group("default") .pathsToMatch(DEFAULT_API_PATH) - .pathsToExclude("/error", ADMIN_API_PATH) .packagesToScan("com.cubetiqs.web") .build() } - @Bean - fun adminApi(): GroupedOpenApi { - return GroupedOpenApi.builder() - .group("admin") - .pathsToMatch(ADMIN_API_PATH) - .build() - } - @Bean fun cubetiqOpenAPI(): OpenAPI { return OpenAPI() diff --git a/api/src/main/kotlin/com/cubetiqs/web/controller/CustomerController.kt b/api/src/main/kotlin/com/cubetiqs/web/controller/CustomerController.kt new file mode 100644 index 0000000..c878714 --- /dev/null +++ b/api/src/main/kotlin/com/cubetiqs/web/controller/CustomerController.kt @@ -0,0 +1,29 @@ +package com.cubetiqs.web.controller + +import com.cubetiqs.web.infrastructure.data.Customer +import com.cubetiqs.web.infrastructure.repository.CustomerRepository +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.web.bind.annotation.* + +@Tag(name = "Customer") +@RestController +@RequestMapping("/customers") +class CustomerController @Autowired constructor( + private val customerRepository: CustomerRepository, +) { + @GetMapping + fun getAll(): List = customerRepository.findAll() + + @GetMapping("/{id}") + fun getById(@PathVariable id: String): Customer = customerRepository.findById(id).orElse(null) + + @PostMapping + fun create(@RequestBody customer: Customer) = customerRepository.save(customer) + + @DeleteMapping("/{id}") + fun delete(@PathVariable id: String) = customerRepository.deleteById(id) + + @PutMapping("/{id}") + fun update(@PathVariable id: String, @RequestBody customer: Customer) = customerRepository.save(customer) +} \ No newline at end of file diff --git a/api/src/main/kotlin/com/cubetiqs/web/controller/IndexController.kt b/api/src/main/kotlin/com/cubetiqs/web/controller/IndexController.kt index 492949c..3cc3a60 100644 --- a/api/src/main/kotlin/com/cubetiqs/web/controller/IndexController.kt +++ b/api/src/main/kotlin/com/cubetiqs/web/controller/IndexController.kt @@ -12,6 +12,7 @@ import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController +import java.net.InetAddress @Tag(name = "Miscellaneous") @RestController @@ -26,14 +27,16 @@ class IndexController @Autowired constructor( ApiInfoAuthorResponse(name = "Sambo Chea", email = "sombochea@cubetiqs.com"), ApiInfoAuthorResponse(name = "CUBETIQ OSS", email = "oss@cubetiqs.com"), ) + val hostname = InetAddress.getLocalHost().hostName val response = ApiInfoResponse( info = "API Operation is running normally on ${environment.activeProfiles.joinToString(separator = ",")}", - name = buildProperties.name, + name = environment.getProperty("spring.application.name") ?: buildProperties.name, service = buildProperties.artifact, version = buildProperties.version, date = buildProperties.time.toString(), commit = buildProperties["commitId"], authors = authors, + hostname = hostname, ) return response(response) } diff --git a/api/src/main/kotlin/com/cubetiqs/web/controller/admin/AdminController.kt b/api/src/main/kotlin/com/cubetiqs/web/controller/admin/AdminController.kt deleted file mode 100644 index f851765..0000000 --- a/api/src/main/kotlin/com/cubetiqs/web/controller/admin/AdminController.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.cubetiqs.web.controller.admin - -import com.cubetiqs.web.annotation.ApiBearerAuth -import com.cubetiqs.web.controller.BaseController -import com.cubetiqs.web.util.RouteConstants -import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController - -@Tag(name = "Admin") -@RestController -@RequestMapping(RouteConstants.ADMIN) -class AdminController : BaseController { - @ApiBearerAuth - @GetMapping - fun getAdmin(): String { - return "Admin" - } -} \ No newline at end of file diff --git a/api/src/main/kotlin/com/cubetiqs/web/infrastructure/data/Customer.kt b/api/src/main/kotlin/com/cubetiqs/web/infrastructure/data/Customer.kt new file mode 100644 index 0000000..f4deaaf --- /dev/null +++ b/api/src/main/kotlin/com/cubetiqs/web/infrastructure/data/Customer.kt @@ -0,0 +1,14 @@ +package com.cubetiqs.web.infrastructure.data + +import org.springframework.data.annotation.Id +import org.springframework.data.mongodb.core.mapping.Document + +@Document(collection = "customer") +data class Customer( + @Id + var id: String? = null, + var name: String? = null, + var email: String? = null, + var phone: String? = null, + var address: String? = null, +) \ No newline at end of file diff --git a/api/src/main/kotlin/com/cubetiqs/web/infrastructure/repository/CustomerRepository.kt b/api/src/main/kotlin/com/cubetiqs/web/infrastructure/repository/CustomerRepository.kt new file mode 100644 index 0000000..463ca78 --- /dev/null +++ b/api/src/main/kotlin/com/cubetiqs/web/infrastructure/repository/CustomerRepository.kt @@ -0,0 +1,8 @@ +package com.cubetiqs.web.infrastructure.repository + +import com.cubetiqs.web.infrastructure.data.Customer +import org.springframework.data.mongodb.repository.MongoRepository +import org.springframework.stereotype.Repository + +@Repository +interface CustomerRepository : MongoRepository \ No newline at end of file diff --git a/api/src/main/kotlin/com/cubetiqs/web/model/response/ApiInfoResponse.kt b/api/src/main/kotlin/com/cubetiqs/web/model/response/ApiInfoResponse.kt index fec4996..114c3cb 100644 --- a/api/src/main/kotlin/com/cubetiqs/web/model/response/ApiInfoResponse.kt +++ b/api/src/main/kotlin/com/cubetiqs/web/model/response/ApiInfoResponse.kt @@ -1,7 +1,9 @@ package com.cubetiqs.web.model.response +import com.fasterxml.jackson.annotation.JsonInclude import io.swagger.v3.oas.annotations.media.Schema +@JsonInclude(JsonInclude.Include.NON_NULL) @Schema(name = "ApiInfoResponse", description = "ApiInfoResponse") data class ApiInfoResponse( val name: String, @@ -10,6 +12,7 @@ data class ApiInfoResponse( val version: String, val date: String, val commit: String, + val hostname: String? = null, val authors: Collection = listOf(), ) : BaseRequestModel diff --git a/api/src/main/resources/application.yml b/api/src/main/resources/application.yml index bea3b1f..ee9aa02 100644 --- a/api/src/main/resources/application.yml +++ b/api/src/main/resources/application.yml @@ -2,8 +2,10 @@ spring: profiles: active: ${APP_PROFILE:dev} application: - name: cubetiq-api-service - + name: ${APP_NAME:cubetiq-api-service} + data: + mongodb: + uri: ${MONGODB_URI:mongodb://192.168.0.202:27017/spring-web-api-db} cubetiq: app: data-dir: ${APP_DATA_DIR:${user.home}/${spring.application.name}} diff --git a/k8s/1-namespace.yaml b/k8s/1-namespace.yaml new file mode 100644 index 0000000..52da2fd --- /dev/null +++ b/k8s/1-namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + app: spring-dev + name: spring-dev diff --git a/k8s/2-secret.yaml b/k8s/2-secret.yaml new file mode 100644 index 0000000..0375191 --- /dev/null +++ b/k8s/2-secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + namespace: spring-dev + name: registry-secret +stringData: + .dockerconfigjson: | + {"auths":{"registry.kh.cubetiqs.com":{"auth":"c29tYm9jaGVhOm1z"}}} +type: kubernetes.io/dockerconfigjson \ No newline at end of file diff --git a/k8s/3-mongo.yaml b/k8s/3-mongo.yaml new file mode 100644 index 0000000..c590633 --- /dev/null +++ b/k8s/3-mongo.yaml @@ -0,0 +1,50 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: spring-dev + name: mongo-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 256Mi +--- +apiVersion: v1 +kind: Service +metadata: + namespace: spring-dev + name: mongo +spec: + selector: + app: mongo + ports: + - port: 27017 + targetPort: 27017 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: spring-dev + name: mongo +spec: + selector: + matchLabels: + app: mongo + template: + metadata: + labels: + app: mongo + spec: + containers: + - name: mongo + image: mongo + ports: + - containerPort: 27017 + volumeMounts: + - name: storage + mountPath: /data/db + volumes: + - name: storage + persistentVolumeClaim: + claimName: mongo-pvc \ No newline at end of file diff --git a/k8s/app.yaml b/k8s/app.yaml new file mode 100644 index 0000000..edbac66 --- /dev/null +++ b/k8s/app.yaml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: Service +metadata: + namespace: spring-dev + name: spring-web-service +spec: + selector: + app: spring-web-api + ports: + - port: 8080 + targetPort: 8080 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: spring-dev + name: spring-web-api +spec: + replicas: 1 + selector: + matchLabels: + app: spring-web-api + template: + metadata: + labels: + app: spring-web-api + spec: + imagePullSecrets: + - name: registry-secret + containers: + - name: spring-web-app + image: registry.kh.cubetiqs.com/spring-web-api:latest + ports: + - containerPort: 8080 + env: + - name: MONGODB_URI + value: mongodb://mongo:27017/spring-web-api + - name: APP_NAME + value: spring-web-api-hello + imagePullPolicy: Always \ No newline at end of file