diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5cacc73 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.idea/ +.github/ +k8s/ \ No newline at end of file diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..83fd8af --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,104 @@ +name: Docker + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +on: + push: + branches: [ "master" ] + # Publish semver tags as releases. + tags: [ 'v*.*.*' ] + paths-ignore: + - 'k8s/**' + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: ghcr.io + # github.repository as / + IMAGE_NAME: ${{ github.repository }} + + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + # This is used to complete the identity challenge + # with sigstore/fulcio when running outside of PRs. + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Install the cosign tool except on PR + # https://github.com/sigstore/cosign-installer + - name: Install cosign + if: github.event_name != 'pull_request' + uses: sigstore/cosign-installer@7e0881f8fe90b25e305bbf0309761e9314607e25 + with: + cosign-release: 'v1.9.0' + + + # Workaround: https://github.com/docker/build-push-action/issues/461 + - name: Setup Docker buildx + uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf + with: + install: true + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=tag + type=raw,value=latest + type=sha + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a + with: + context: . + platforms: linux/amd64, linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # Sign the resulting Docker image digest except on PRs. + # This will only write to the public Rekor transparency log when the Docker + # repository is public to avoid leaking data. If you would like to publish + # transparency data even for private images, pass --force to cosign below. + # https://github.com/sigstore/cosign + - name: Sign the published Docker image + if: ${{ github.event_name != 'pull_request' }} + env: + COSIGN_EXPERIMENTAL: "true" + # This step uses the identity token to provision an ephemeral certificate + # against the sigstore community Fulcio instance. + run: echo "${{ steps.meta.outputs.tags }}" | xargs -I {} cosign sign {}@${{ steps.build-and-push.outputs.digest }} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a11b769 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM golang:1.19.1-alpine as builder + +WORKDIR /app + +COPY go.mod ./ +COPY go.sum ./ +RUN go mod download + +COPY . ./ + +RUN go build -o /food-track-be + +EXPOSE 8080 + +FROM alpine + +COPY --from=builder /food-track-be . + +CMD [ "/food-details-integrator-be" ] \ No newline at end of file diff --git a/controller/FoodConsumptionController.go b/controller/FoodConsumptionController.go index 1c3671b..41b71db 100644 --- a/controller/FoodConsumptionController.go +++ b/controller/FoodConsumptionController.go @@ -18,66 +18,70 @@ func NewFoodConsumptionController(foodConsumptionService *service.FoodConsumptio func (s *FoodConsumptionController) FindAllConsumptionForMeal(c *gin.Context) { mealId, err := uuid.Parse(c.Param("mealId")) if err != nil { - c.JSON(500, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } foodConsumptionDtos, err := s.foodConsumptionService.FindAllFoodConsumptionForMeal(mealId) if err != nil { - c.JSON(500, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } c.JSON(200, dto.BaseResponse[[]*dto.FoodConsumptionDto]{ - Body: foodConsumptionDtos, - ErrorMessage: "", + Body: foodConsumptionDtos, }) } func (s *FoodConsumptionController) AddFoodConsumption(c *gin.Context) { mealId, err := uuid.Parse(c.Param("mealId")) if err != nil { - c.JSON(400, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } var foodConsumptionDto dto.FoodConsumptionDto err = c.BindJSON(&foodConsumptionDto) if err != nil { - c.JSON(400, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } foodConsumptionDto, err = s.foodConsumptionService.CreateFoodConsumptionForMeal(mealId, foodConsumptionDto) if err != nil { - c.JSON(500, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } c.JSON(200, dto.BaseResponse[dto.FoodConsumptionDto]{ - Body: foodConsumptionDto, - ErrorMessage: "", + Body: foodConsumptionDto, }) } func (s *FoodConsumptionController) UpdateFoodConsumption(c *gin.Context) { mealId, err := uuid.Parse(c.Param("mealId")) if err != nil { - c.JSON(400, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } var foodConsumptionDto dto.FoodConsumptionDto c.BindJSON(&foodConsumptionDto) foodConsumptionDto, err = s.foodConsumptionService.UpdateFoodConsumptionForMeal(mealId, foodConsumptionDto) if err != nil { - c.JSON(500, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } c.JSON(200, dto.BaseResponse[dto.FoodConsumptionDto]{ - Body: foodConsumptionDto, - ErrorMessage: "", + Body: foodConsumptionDto, }) } @@ -85,17 +89,19 @@ func (s *FoodConsumptionController) DeleteFoodConsumption(c *gin.Context) { mealId, err := uuid.Parse(c.Param("mealId")) foodConsumptionId, err := uuid.Parse(c.Param("foodConsumptionId")) if err != nil { - c.JSON(500, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } err = s.foodConsumptionService.DeleteFoodConsumptionForMeal(mealId, foodConsumptionId) if err != nil { - c.JSON(500, dto.BaseResponse[any]{ + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ ErrorMessage: err.Error(), }) + return } c.JSON(200, dto.BaseResponse[any]{ - ErrorMessage: "", + Body: err != nil, }) } diff --git a/controller/MealController.go b/controller/MealController.go index ada73c4..30a9890 100644 --- a/controller/MealController.go +++ b/controller/MealController.go @@ -17,51 +17,88 @@ func NewMealController(mealService *service.MealService) *MealController { func (s *MealController) FindAllMeals(c *gin.Context) { mealDtos, err := s.mealService.FindAll() - response := dto.BaseResponse[[]*dto.MealDto]{ - Body: mealDtos, - ErrorMessage: err.Error(), + if err != nil { + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ + ErrorMessage: err.Error(), + }) + return + } + response := dto.BaseResponse[[]dto.MealDto]{ + Body: mealDtos, } c.JSON(200, response) } func (s *MealController) FindMealById(c *gin.Context) { - id, _ := uuid.Parse(c.Param("id")) + id, _ := uuid.Parse(c.Param("mealId")) mealDto, err := s.mealService.FindById(id) + if err != nil { + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ + ErrorMessage: err.Error(), + }) + return + } response := dto.BaseResponse[dto.MealDto]{ - Body: mealDto, - ErrorMessage: err.Error(), + Body: mealDto, } c.JSON(200, response) } func (s *MealController) CreateMeal(c *gin.Context) { var mealDto dto.MealDto - c.BindJSON(&mealDto) - mealDto, err := s.mealService.Create(mealDto) + err := c.BindJSON(&mealDto) + if err != nil { + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ + ErrorMessage: err.Error(), + }) + return + } + mealDto, err = s.mealService.Create(mealDto) + if err != nil { + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ + ErrorMessage: err.Error(), + }) + return + } response := dto.BaseResponse[dto.MealDto]{ - Body: mealDto, - ErrorMessage: err.Error(), + Body: mealDto, } c.JSON(200, response) } func (s *MealController) UpdateMeal(c *gin.Context) { var mealDto dto.MealDto - c.BindJSON(&mealDto) - mealDto, err := s.mealService.Update(mealDto) + err := c.BindJSON(&mealDto) + if err != nil { + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ + ErrorMessage: err.Error(), + }) + return + } + mealDto, err = s.mealService.Update(mealDto) + if err != nil { + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ + ErrorMessage: err.Error(), + }) + return + } response := dto.BaseResponse[dto.MealDto]{ - Body: mealDto, - ErrorMessage: err.Error(), + Body: mealDto, } c.JSON(200, response) } func (s *MealController) DeleteMeal(c *gin.Context) { - id, _ := uuid.Parse(c.Param("id")) + id, _ := uuid.Parse(c.Param("mealsId")) err := s.mealService.Delete(id) + if err != nil { + c.AbortWithStatusJSON(200, dto.BaseResponse[any]{ + ErrorMessage: err.Error(), + }) + return + } response := dto.BaseResponse[bool]{ - Body: err == nil, - ErrorMessage: err.Error(), + Body: err == nil, } c.JSON(200, response) } diff --git a/go.mod b/go.mod index 382f57f..c0d7aae 100644 --- a/go.mod +++ b/go.mod @@ -2,27 +2,30 @@ module food-track-be go 1.19 +require ( + github.com/gin-gonic/gin v1.8.1 + github.com/google/uuid v1.3.0 + github.com/mashingan/smapping v0.1.19 + github.com/uptrace/bun v1.1.8 + github.com/uptrace/bun/dialect/pgdialect v1.1.8 + github.com/uptrace/bun/driver/pgdriver v1.1.8 +) + require ( github.com/gin-contrib/sse v0.1.0 // indirect - github.com/gin-gonic/gin v1.8.1 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.11.1 // indirect github.com/goccy/go-json v0.9.11 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect - github.com/mashingan/smapping v0.1.19 // indirect github.com/mattn/go-isatty v0.0.16 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/ugorji/go/codec v1.2.7 // indirect - github.com/uptrace/bun v1.1.8 // indirect - github.com/uptrace/bun/dialect/pgdialect v1.1.8 // indirect - github.com/uptrace/bun/driver/pgdriver v1.1.8 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be // indirect diff --git a/go.sum b/go.sum index 6347b63..206557d 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,12 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= @@ -15,6 +17,7 @@ github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4 github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -25,9 +28,11 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= @@ -43,8 +48,10 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -52,10 +59,10 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= -github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= @@ -87,18 +94,21 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= mellium.im/sasl v0.3.0 h1:0qoaTCTo5Py7u/g0cBIQZcMOgG/5LM71nshbXwznBh8= mellium.im/sasl v0.3.0/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= diff --git a/k8s/base/deployment.yaml b/k8s/base/deployment.yaml new file mode 100644 index 0000000..a3880b8 --- /dev/null +++ b/k8s/base/deployment.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: food-track-be-deployment +spec: + template: + spec: + containers: + - name: food-track-be-container + image: food-details-integrator-be-image + ports: + - containerPort: 8080 + livenessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 5 + readinessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 5 + envFrom: + - configMapRef: + name: food-track-be-properties \ No newline at end of file diff --git a/k8s/base/kustomization.yaml b/k8s/base/kustomization.yaml new file mode 100644 index 0000000..4fe69dd --- /dev/null +++ b/k8s/base/kustomization.yaml @@ -0,0 +1,8 @@ +resources: + - deployment.yaml + - service.yaml +commonLabels: + app: food-track-be +images: + - name: food-details-integrator-be-image + newName: ghcr.io/nico-iaco/food-track-be \ No newline at end of file diff --git a/k8s/base/service.yaml b/k8s/base/service.yaml new file mode 100644 index 0000000..93cacc3 --- /dev/null +++ b/k8s/base/service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: food-track-be-service +spec: + type: NodePort + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP diff --git a/k8s/overlays/qa/deployment_patch.yaml b/k8s/overlays/qa/deployment_patch.yaml new file mode 100644 index 0000000..7688bb1 --- /dev/null +++ b/k8s/overlays/qa/deployment_patch.yaml @@ -0,0 +1,15 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: food-track-be-deployment +spec: + replicas: 1 + template: + spec: + containers: + - name: food-track-be-container + resources: + limits: + memory: "500Mi" + requests: + memory: "256Mi" \ No newline at end of file diff --git a/k8s/overlays/qa/kustomization.yaml b/k8s/overlays/qa/kustomization.yaml new file mode 100644 index 0000000..b353596 --- /dev/null +++ b/k8s/overlays/qa/kustomization.yaml @@ -0,0 +1,18 @@ +namespace: grocery +resources: + - ../../base +commonLabels: + app: food-track-be +configMapGenerator: + - name: food-track-be-properties + literals: + - PORT=8080 + - GIN_MODE=release + - DB_HOST=192.168.86.6 + - DB_NAME=food_track + - DB_PASSWORD=3cK@0kh#6U6f + - DB_PORT=5432 + - DB_USER=foodtrack + - GROCERY_BASE_URL=http://grocery-be-service.grocery.svc.cluster.local:8000 +patchesStrategicMerge: + - deployment_patch.yaml \ No newline at end of file diff --git a/main.go b/main.go index 9a53027..7683833 100644 --- a/main.go +++ b/main.go @@ -8,17 +8,33 @@ import ( "github.com/uptrace/bun" "github.com/uptrace/bun/dialect/pgdialect" "github.com/uptrace/bun/driver/pgdriver" + "log" "net/http" "os" + "time" "github.com/gin-gonic/gin" ) func main() { - dsn := os.ExpandEnv("postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME") - sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(dsn))) + //dsn := os.ExpandEnv("postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME") + + //log.Println("connecting to database ", dsn) + pgconn := pgdriver.NewConnector( + pgdriver.WithAddr(os.Getenv("DB_HOST")+":"+os.Getenv("DB_PORT")), + pgdriver.WithUser(os.Getenv("DB_USER")), + pgdriver.WithPassword(os.Getenv("DB_PASSWORD")), + pgdriver.WithDatabase(os.Getenv("DB_NAME")), + pgdriver.WithInsecure(true), + pgdriver.WithTimeout(5*time.Second), + pgdriver.WithDialTimeout(5*time.Second), + pgdriver.WithReadTimeout(5*time.Second), + pgdriver.WithWriteTimeout(5*time.Second), + ) + sqldb := sql.OpenDB(pgconn) db := bun.NewDB(sqldb, pgdialect.New()) + log.Println(db.Ping()) mr := repository.NewMealRepository(*db) fcr := repository.NewFoodConsumptionRepository(*db) @@ -29,16 +45,16 @@ func main() { fcc := controller.NewFoodConsumptionController(fcs) r := gin.Default() - r.GET("/meals", mc.FindAllMeals) - r.GET("/meals/:id", mc.FindMealById) - r.POST("/meals", mc.CreateMeal) - r.PATCH("/meals", mc.UpdateMeal) - r.DELETE("/meals/:id", mc.DeleteMeal) + r.GET("/meal", mc.FindAllMeals) + r.GET("/meal/:mealId", mc.FindMealById) + r.POST("/meal", mc.CreateMeal) + r.PATCH("/meal", mc.UpdateMeal) + r.DELETE("/meal/:mealId", mc.DeleteMeal) - r.GET("/meals/:mealsId/consumption", fcc.FindAllConsumptionForMeal) - r.POST("/meals/:mealsId/consumption", fcc.AddFoodConsumption) - r.PATCH("/meals/:mealsId/consumption/:consumptionId", fcc.UpdateFoodConsumption) - r.DELETE("/meals/:mealsId/consumption/:foodConsumptionId", fcc.DeleteFoodConsumption) + r.GET("/meal/:mealId/consumption", fcc.FindAllConsumptionForMeal) + r.POST("/meal/:mealId/consumption", fcc.AddFoodConsumption) + r.PATCH("/meal/:mealId/consumption/:consumptionId", fcc.UpdateFoodConsumption) + r.DELETE("/meal/:mealId/consumption/:foodConsumptionId", fcc.DeleteFoodConsumption) r.GET("/ping", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ diff --git a/model/FoodConsumption.go b/model/FoodConsumption.go index ee420d2..3c73134 100644 --- a/model/FoodConsumption.go +++ b/model/FoodConsumption.go @@ -16,3 +16,18 @@ type FoodConsumption struct { Unit string Kcal float32 } + +/* +DDL for table food_consumption (First create Meal table) +create table food_consumption ( +id uuid primary key, +meal_id uuid not null, +food_id uuid not null, +transaction_id uuid not null, +quantity_used float not null, +quantity_used_std float not null, +unit varchar(255) not null, +kcal float not null, +foreign key (meal_id) references meal(id) +); +*/ diff --git a/model/Meal.go b/model/Meal.go index 72bc28f..d729c48 100644 --- a/model/Meal.go +++ b/model/Meal.go @@ -3,17 +3,18 @@ package model import ( "github.com/google/uuid" "github.com/uptrace/bun" + "time" ) type Meal struct { - bun.BaseModel `bun:"table:meal,alias:m"` - ID uuid.UUID `bun:"type:uuid,nullzero,pk"` - Name string `bun:"type:varchar(255),notnull"` - Description string `bun:"type:varchar(255),nullzero"` - MealType MealType `bun:"type:varchar(255),notnull"` - //FoodTypes []FoodType `bun:"type:varchar(255)[]"` - Date string `bun:"type:varchar(255),notnull"` + bun.BaseModel `bun:"table:meal,alias:m"` + ID uuid.UUID `bun:"type:uuid,nullzero,pk"` + Name string `bun:"type:varchar(255),notnull"` + Description string `bun:"type:varchar(255),nullzero"` + MealType MealType `bun:"type:varchar(255),notnull"` + Date time.Time `bun:"type:date,notnull"` FoodConsumptions []*FoodConsumption `bun:"rel:has-many,join:id=meal_id"` + //FoodTypes []FoodType `bun:"type:varchar(255)[]"` } type MealType string @@ -34,3 +35,14 @@ const ( Bitter FoodType = "bitter" Beverage FoodType = "beverage" ) + +/* +DDL for table meal +create table meal ( +id uuid primary key, +name varchar(255) not null, +description varchar(255), +meal_type varchar(255) not null, +date date not null +); +*/ diff --git a/model/dto/FoodTransactionDto.go b/model/dto/FoodTransactionDto.go index df22f38..9cacdcc 100644 --- a/model/dto/FoodTransactionDto.go +++ b/model/dto/FoodTransactionDto.go @@ -2,7 +2,6 @@ package dto import ( "github.com/google/uuid" - "time" ) type FoodTransactionDto struct { @@ -12,5 +11,5 @@ type FoodTransactionDto struct { AvailableQuantity float32 `json:"availableQuantity"` Unit string `json:"unit"` Price float32 `json:"price"` - ExpirationDate time.Time `json:"expirationDate"` + //ExpirationDate time.Time `json:"expirationDate"` } diff --git a/model/dto/MealDto.go b/model/dto/MealDto.go index b59fe13..2a451f3 100644 --- a/model/dto/MealDto.go +++ b/model/dto/MealDto.go @@ -1,12 +1,16 @@ package dto -import "time" +import ( + "food-track-be/model" + "github.com/google/uuid" + "time" +) type MealDto struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - MealType string `json:"mealType"` + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + MealType model.MealType `json:"mealType"` + Date time.Time `json:"date"` //FoodTypes []string `json:"foodTypes"` - Date time.Time `json:"date"` } diff --git a/service/FoodConsumptionService.go b/service/FoodConsumptionService.go index c533ff8..6968b6f 100644 --- a/service/FoodConsumptionService.go +++ b/service/FoodConsumptionService.go @@ -23,8 +23,15 @@ func (s FoodConsumptionService) FindAllFoodConsumptionForMeal(mealId uuid.UUID) if err != nil { return nil, err } - mappedField := smapping.MapFields(foodConsumptions) - err = smapping.FillStruct(&foodConsumptionsDto, mappedField) + for _, foodConsumption := range foodConsumptions { + foodConsumptionDto := dto.FoodConsumptionDto{} + mappedField := smapping.MapFields(&foodConsumption) + err = smapping.FillStruct(&foodConsumptionDto, mappedField) + if err != nil { + return nil, err + } + foodConsumptionsDto = append(foodConsumptionsDto, &foodConsumptionDto) + } if err != nil { return []*dto.FoodConsumptionDto{}, err } @@ -45,14 +52,14 @@ func (s FoodConsumptionService) CreateFoodConsumptionForMeal(mealId uuid.UUID, f return dto.FoodConsumptionDto{}, err } transactionDto.AvailableQuantity -= foodConsumptionDto.QuantityUsed - _, err = s.groceryService.UpdateFoodTransaction(foodConsumptionDto.TransactionId, transactionDto) + _, err = s.groceryService.UpdateFoodTransaction(foodConsumptionDto.FoodId, transactionDto) if err != nil { return dto.FoodConsumptionDto{}, err } _, err = s.repository.Create(&foodConsumption) if err != nil { transactionDto.AvailableQuantity += foodConsumptionDto.QuantityUsed - _, err = s.groceryService.UpdateFoodTransaction(foodConsumptionDto.TransactionId, transactionDto) + _, err = s.groceryService.UpdateFoodTransaction(foodConsumptionDto.FoodId, transactionDto) if err != nil { return dto.FoodConsumptionDto{}, err } @@ -84,14 +91,14 @@ func (s FoodConsumptionService) UpdateFoodConsumptionForMeal(mealId uuid.UUID, f return dto.FoodConsumptionDto{}, err } transactionDto.AvailableQuantity += deltaQuantity - _, err = s.groceryService.UpdateFoodTransaction(foodConsumptionDto.TransactionId, transactionDto) + _, err = s.groceryService.UpdateFoodTransaction(foodConsumptionDto.FoodId, transactionDto) if err != nil { return dto.FoodConsumptionDto{}, err } _, err = s.repository.Update(&foodConsumption) if err != nil { transactionDto.AvailableQuantity -= deltaQuantity - _, err = s.groceryService.UpdateFoodTransaction(foodConsumptionDto.TransactionId, transactionDto) + _, err = s.groceryService.UpdateFoodTransaction(foodConsumptionDto.FoodId, transactionDto) if err != nil { return dto.FoodConsumptionDto{}, err } @@ -115,14 +122,14 @@ func (s FoodConsumptionService) DeleteFoodConsumptionForMeal(mealId uuid.UUID, f return err } transactionDto.AvailableQuantity += foodConsumption.QuantityUsed - _, err = s.groceryService.UpdateFoodTransaction(foodConsumption.TransactionId, transactionDto) + _, err = s.groceryService.UpdateFoodTransaction(foodConsumption.FoodId, transactionDto) if err != nil { return err } _, err = s.repository.DeleteFoodConsumptionForMeal(mealId, foodConsumptionId) if err != nil { transactionDto.AvailableQuantity -= foodConsumption.QuantityUsed - _, err = s.groceryService.UpdateFoodTransaction(foodConsumption.TransactionId, transactionDto) + _, err = s.groceryService.UpdateFoodTransaction(foodConsumption.FoodId, transactionDto) if err != nil { return err } diff --git a/service/GroceryService.go b/service/GroceryService.go index 7bae5e9..29fe85b 100644 --- a/service/GroceryService.go +++ b/service/GroceryService.go @@ -3,6 +3,7 @@ package service import ( "bytes" "encoding/json" + "errors" "food-track-be/model/dto" "github.com/google/uuid" "io" @@ -19,7 +20,9 @@ func NewGroceryService() *GroceryService { } func getCall(url string) ([]byte, error) { - response, err := http.Get(url) + request, err := http.NewRequest(http.MethodGet, url, nil) + request.Header.Add("Content-Type", "application/json") + response, err := http.DefaultClient.Do(request) if err != nil { return nil, err } @@ -30,6 +33,7 @@ func patchCall(url string, body any) ([]byte, error) { var buf bytes.Buffer err := json.NewEncoder(&buf).Encode(body) request, err := http.NewRequest(http.MethodPatch, url, &buf) + request.Header.Add("Content-Type", "application/json") if err != nil { return nil, err } @@ -89,5 +93,8 @@ func (s *GroceryService) UpdateFoodTransaction(foodId uuid.UUID, foodTransaction if err != nil { return dto.FoodTransactionDto{}, err } + if response.ErrorMessage != "" { + return dto.FoodTransactionDto{}, errors.New(response.ErrorMessage) + } return response.Body, nil } diff --git a/service/MealService.go b/service/MealService.go index 5b17559..f4d4b98 100644 --- a/service/MealService.go +++ b/service/MealService.go @@ -16,16 +16,23 @@ func NewMealService(repository *repository.MealRepository) *MealService { return &MealService{repository: repository} } -func (s *MealService) FindAll() ([]*dto.MealDto, error) { - var mealsDto []*dto.MealDto +func (s *MealService) FindAll() ([]dto.MealDto, error) { + var mealsDto []dto.MealDto meals, err := s.repository.FindAll() if err != nil { return nil, err } - mappedField := smapping.MapFields(meals) - err = smapping.FillStruct(&mealsDto, mappedField) + for _, meal := range meals { + mealDto := dto.MealDto{} + mappedField := smapping.MapFields(&meal) + err = smapping.FillStruct(&mealDto, mappedField) + if err != nil { + return nil, err + } + mealsDto = append(mealsDto, mealDto) + } if err != nil { - return []*dto.MealDto{}, err + return []dto.MealDto{}, err } return mealsDto, nil }