diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 899cc78..3388b3b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -88,6 +88,7 @@ jobs: - {folder: inventory-service-mock, name: inventory} - {folder: inventory-service-mock-go, name: inventory-go} - {folder: order, name: orders} + - {folder: order-go, name: orders-go} steps: - uses: actions/checkout@v4 diff --git a/bestseller-toys-go/Dockerfile b/bestseller-toys-go/Dockerfile index 0ecb1cc..cec36c4 100644 --- a/bestseller-toys-go/Dockerfile +++ b/bestseller-toys-go/Dockerfile @@ -1,5 +1,5 @@ # Use official Golang image as builder -FROM golang:1.23 AS builder +FROM golang:1.22 AS builder WORKDIR /app diff --git a/bestseller-toys-go/go.mod b/bestseller-toys-go/go.mod index 5699e81..0e16cbb 100644 --- a/bestseller-toys-go/go.mod +++ b/bestseller-toys-go/go.mod @@ -1,6 +1,6 @@ module bestseller-toys -go 1.23.4 +go 1.22 require ( github.com/google/uuid v1.6.0 diff --git a/bestseller-toys-go/products.db b/bestseller-toys-go/products.db deleted file mode 100644 index 20e60c9..0000000 Binary files a/bestseller-toys-go/products.db and /dev/null differ diff --git a/charts/steadybit-shopping-demo/Chart.yaml b/charts/steadybit-shopping-demo/Chart.yaml index 8fc14ea..b1454e2 100644 --- a/charts/steadybit-shopping-demo/Chart.yaml +++ b/charts/steadybit-shopping-demo/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: steadybit-shopping-demo description: Steadybit shopping-demo application Helm chart for Kubernetes. -version: 1.1.9 +version: 1.1.13 appVersion: latest type: application home: https://www.steadybit.com/ diff --git a/charts/steadybit-shopping-demo/templates/4-bestseller-toys-deployment.yml b/charts/steadybit-shopping-demo/templates/4-bestseller-toys-deployment.yml index 7b8a0c2..89a9e78 100644 --- a/charts/steadybit-shopping-demo/templates/4-bestseller-toys-deployment.yml +++ b/charts/steadybit-shopping-demo/templates/4-bestseller-toys-deployment.yml @@ -70,14 +70,14 @@ spec: httpGet: path: /actuator/health/liveness port: 8081 - initialDelaySeconds: 60 + initialDelaySeconds: 10 timeoutSeconds: 3 periodSeconds: 10 readinessProbe: httpGet: path: /actuator/health/readiness port: 8081 - initialDelaySeconds: 60 + initialDelaySeconds: 10 timeoutSeconds: 5 periodSeconds: 10 {{- with .Values.bestsellerToys.nodeSelector }} diff --git a/charts/steadybit-shopping-demo/templates/6-inventory-service-mock-deployment.yml b/charts/steadybit-shopping-demo/templates/6-inventory-service-mock-deployment.yml index f8f124b..4645d16 100644 --- a/charts/steadybit-shopping-demo/templates/6-inventory-service-mock-deployment.yml +++ b/charts/steadybit-shopping-demo/templates/6-inventory-service-mock-deployment.yml @@ -58,14 +58,14 @@ spec: httpGet: path: /actuator/health/liveness port: 8084 - initialDelaySeconds: 30 + initialDelaySeconds: 10 timeoutSeconds: 3 periodSeconds: 10 readinessProbe: httpGet: path: /actuator/health/readiness port: 8084 - initialDelaySeconds: 30 + initialDelaySeconds: 10 timeoutSeconds: 5 periodSeconds: 10 affinity: diff --git a/charts/steadybit-shopping-demo/templates/7-activemq-deployment.yml b/charts/steadybit-shopping-demo/templates/7-activemq-deployment.yml index b2e242f..6832c36 100644 --- a/charts/steadybit-shopping-demo/templates/7-activemq-deployment.yml +++ b/charts/steadybit-shopping-demo/templates/7-activemq-deployment.yml @@ -53,6 +53,8 @@ spec: ports: - containerPort: 61616 protocol: TCP + - containerPort: 61613 + protocol: TCP env: - name: DD_SERVICE valueFrom: @@ -164,8 +166,13 @@ metadata: spec: ports: - port: 61616 + name: openwire protocol: TCP targetPort: 61616 + - port: 61613 + name: stomp + protocol: TCP + targetPort: 61613 selector: run: activemq type: ClusterIP diff --git a/charts/steadybit-shopping-demo/templates/9-orders-deployment.yml b/charts/steadybit-shopping-demo/templates/9-orders-deployment.yml index 48c96d2..a47bc8e 100644 --- a/charts/steadybit-shopping-demo/templates/9-orders-deployment.yml +++ b/charts/steadybit-shopping-demo/templates/9-orders-deployment.yml @@ -54,14 +54,14 @@ spec: httpGet: path: /actuator/health/liveness port: 8086 - initialDelaySeconds: 30 + initialDelaySeconds: 10 timeoutSeconds: 3 periodSeconds: 10 readinessProbe: httpGet: path: /actuator/health/readiness port: 8086 - initialDelaySeconds: 30 + initialDelaySeconds: 10 timeoutSeconds: 5 periodSeconds: 10 imagePullPolicy: Always @@ -70,6 +70,8 @@ spec: - containerPort: 8086 protocol: TCP env: + - name: ACTIVEMQ_BROKER_HOST + value: {{.Values.orders.activeMQ.host}} - name: SPRING_PROFILES_ACTIVE value: "kubernetes" - name: DD_SERVICE diff --git a/charts/steadybit-shopping-demo/tests/__snapshot__/4-bestseller-toys-deployment_test.yaml.snap b/charts/steadybit-shopping-demo/tests/__snapshot__/4-bestseller-toys-deployment_test.yaml.snap index 5c1b9c7..58b2f9a 100644 --- a/charts/steadybit-shopping-demo/tests/__snapshot__/4-bestseller-toys-deployment_test.yaml.snap +++ b/charts/steadybit-shopping-demo/tests/__snapshot__/4-bestseller-toys-deployment_test.yaml.snap @@ -60,7 +60,7 @@ manifest should match snapshot: httpGet: path: /actuator/health/liveness port: 8081 - initialDelaySeconds: 60 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 name: toys-bestseller @@ -71,7 +71,7 @@ manifest should match snapshot: httpGet: path: /actuator/health/readiness port: 8081 - initialDelaySeconds: 60 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 resources: @@ -175,7 +175,7 @@ manifest should match snapshot replica count: httpGet: path: /actuator/health/liveness port: 8081 - initialDelaySeconds: 60 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 name: toys-bestseller @@ -186,7 +186,7 @@ manifest should match snapshot replica count: httpGet: path: /actuator/health/readiness port: 8081 - initialDelaySeconds: 60 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 resources: diff --git a/charts/steadybit-shopping-demo/tests/__snapshot__/6-inventory-service-mock-deployment_test.yaml.snap b/charts/steadybit-shopping-demo/tests/__snapshot__/6-inventory-service-mock-deployment_test.yaml.snap index 2a5371e..9a90287 100644 --- a/charts/steadybit-shopping-demo/tests/__snapshot__/6-inventory-service-mock-deployment_test.yaml.snap +++ b/charts/steadybit-shopping-demo/tests/__snapshot__/6-inventory-service-mock-deployment_test.yaml.snap @@ -58,7 +58,7 @@ manifest should match snapshot: httpGet: path: /actuator/health/liveness port: 8084 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 name: inventory @@ -69,7 +69,7 @@ manifest should match snapshot: httpGet: path: /actuator/health/readiness port: 8084 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 resources: @@ -171,7 +171,7 @@ manifest should match snapshot replica count: httpGet: path: /actuator/health/liveness port: 8084 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 name: inventory @@ -182,7 +182,7 @@ manifest should match snapshot replica count: httpGet: path: /actuator/health/readiness port: 8084 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 resources: diff --git a/charts/steadybit-shopping-demo/tests/__snapshot__/7-activemq-deployment_test.yaml.snap b/charts/steadybit-shopping-demo/tests/__snapshot__/7-activemq-deployment_test.yaml.snap index 44abf89..29c2f76 100644 --- a/charts/steadybit-shopping-demo/tests/__snapshot__/7-activemq-deployment_test.yaml.snap +++ b/charts/steadybit-shopping-demo/tests/__snapshot__/7-activemq-deployment_test.yaml.snap @@ -65,6 +65,8 @@ manifest should match snapshot: ports: - containerPort: 61616 protocol: TCP + - containerPort: 61613 + protocol: TCP readinessProbe: initialDelaySeconds: 15 periodSeconds: 10 @@ -163,9 +165,14 @@ manifest should match snapshot: namespace: NAMESPACE spec: ports: - - port: 61616 + - name: openwire + port: 61616 protocol: TCP targetPort: 61616 + - name: stomp + port: 61613 + protocol: TCP + targetPort: 61613 selector: run: activemq type: ClusterIP @@ -247,6 +254,8 @@ manifest should match snapshot replica count: ports: - containerPort: 61616 protocol: TCP + - containerPort: 61613 + protocol: TCP readinessProbe: initialDelaySeconds: 15 periodSeconds: 10 @@ -345,9 +354,14 @@ manifest should match snapshot replica count: namespace: NAMESPACE spec: ports: - - port: 61616 + - name: openwire + port: 61616 protocol: TCP targetPort: 61616 + - name: stomp + port: 61613 + protocol: TCP + targetPort: 61613 selector: run: activemq type: ClusterIP diff --git a/charts/steadybit-shopping-demo/tests/__snapshot__/9-orders-deployment_test.yaml.snap b/charts/steadybit-shopping-demo/tests/__snapshot__/9-orders-deployment_test.yaml.snap index c6c121e..c03ca6e 100644 --- a/charts/steadybit-shopping-demo/tests/__snapshot__/9-orders-deployment_test.yaml.snap +++ b/charts/steadybit-shopping-demo/tests/__snapshot__/9-orders-deployment_test.yaml.snap @@ -32,6 +32,8 @@ manifest should match snapshot: spec: containers: - env: + - name: ACTIVEMQ_BROKER_HOST + value: localhost:61613 - name: SPRING_PROFILES_ACTIVE value: kubernetes - name: DD_SERVICE @@ -48,7 +50,7 @@ manifest should match snapshot: httpGet: path: /actuator/health/liveness port: 8086 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 name: orders @@ -59,7 +61,7 @@ manifest should match snapshot: httpGet: path: /actuator/health/readiness port: 8086 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 resources: @@ -124,6 +126,8 @@ manifest should match snapshot replica count: spec: containers: - env: + - name: ACTIVEMQ_BROKER_HOST + value: localhost:61613 - name: SPRING_PROFILES_ACTIVE value: kubernetes - name: DD_SERVICE @@ -140,7 +144,7 @@ manifest should match snapshot replica count: httpGet: path: /actuator/health/liveness port: 8086 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 name: orders @@ -151,7 +155,7 @@ manifest should match snapshot replica count: httpGet: path: /actuator/health/readiness port: 8086 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 resources: @@ -226,6 +230,8 @@ manifest should match snapshot with horizontalPodAutoscaler and podDisruptionBud topologyKey: topology.kubernetes.io/zone containers: - env: + - name: ACTIVEMQ_BROKER_HOST + value: localhost:61613 - name: SPRING_PROFILES_ACTIVE value: kubernetes - name: DD_SERVICE @@ -242,7 +248,7 @@ manifest should match snapshot with horizontalPodAutoscaler and podDisruptionBud httpGet: path: /actuator/health/liveness port: 8086 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 3 name: orders @@ -253,7 +259,7 @@ manifest should match snapshot with horizontalPodAutoscaler and podDisruptionBud httpGet: path: /actuator/health/readiness port: 8086 - initialDelaySeconds: 30 + initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 resources: diff --git a/charts/steadybit-shopping-demo/values.yaml b/charts/steadybit-shopping-demo/values.yaml index a389973..14791ec 100644 --- a/charts/steadybit-shopping-demo/values.yaml +++ b/charts/steadybit-shopping-demo/values.yaml @@ -213,3 +213,6 @@ orders: podDisruptionBudget: false # nodeSelector -- Node labels for pod assignment nodeSelector: {} + activeMQ: + # ActiveMQ Host + host: "localhost:61613" diff --git a/docker-compose.yml b/docker-compose.yml index 490af2d..f365960 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,40 +2,40 @@ version: '3.3' services: gateway: - image: steadybit/gateway:1.0.0-SNAPSHOT + image: steadybit/gateway:develop ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: docker fashion: - image: steadybit/bestseller-fashion:1.0.0-SNAPSHOT + image: steadybit/bestseller-fashion:develop ports: - "8082:8082" environment: "rest.endpoint.inventory": "http://inventory:8084/inventory" toys: - image: steadybit/bestseller-toys:1.0.0-SNAPSHOT + image: steadybit/bestseller-toys-go:develop ports: - "8081:8081" environment: "rest.endpoint.inventory": "http://inventory:8084/inventory" hot-deals: - image: steadybit/hot-deals:1.0.0-SNAPSHOT + image: steadybit/hot-deals:develop ports: - "8083:8083" environment: "rest.endpoint.inventory": "http://inventory:8084/inventory" inventory: - image: steadybit/inventory:1.0.0-SNAPSHOT + image: steadybit/inventory-go:develop ports: - "8084:8084" checkout: - image: steadybit/checkout:1.0.0-SNAPSHOT + image: steadybit/checkout:develop ports: - "8085:8085" environment: @@ -44,7 +44,7 @@ services: - activemq orders: - image: steadybit/orders:1.0.0-SNAPSHOT + image: steadybit/orders-go:develop environment: "spring.activemq.broker-url": "tcp://activemq:61616" depends_on: @@ -55,6 +55,7 @@ services: container_name: 'activemq' ports: - "61616:61616" + - "61613:61613" - "8161:8161" volumes: - ${PWD}/activemq.xml:/opt/activemq/conf/activemq.xml diff --git a/inventory-service-mock-go/Dockerfile b/inventory-service-mock-go/Dockerfile index f07b11e..f6d4212 100644 --- a/inventory-service-mock-go/Dockerfile +++ b/inventory-service-mock-go/Dockerfile @@ -1,5 +1,5 @@ # Use official Golang image as builder -FROM golang:1.23 AS builder +FROM golang:1.22 AS builder WORKDIR /app diff --git a/inventory-service-mock-go/Makefile b/inventory-service-mock-go/Makefile index 3059b5d..b82d282 100644 --- a/inventory-service-mock-go/Makefile +++ b/inventory-service-mock-go/Makefile @@ -8,7 +8,7 @@ docker-build: docker build -t inventory-service-mock . docker-run: - docker run -p 8080:8080 inventory-service-mock + docker run -p 8084:8084 inventory-service-mock ## licenses-report: generate a report of all licenses .PHONY: licenses-report diff --git a/inventory-service-mock-go/go.mod b/inventory-service-mock-go/go.mod index ac9dfb1..ff9e6f8 100644 --- a/inventory-service-mock-go/go.mod +++ b/inventory-service-mock-go/go.mod @@ -1,6 +1,6 @@ module inventory-service-mock -go 1.23.4 +go 1.22 require ( github.com/prometheus/client_golang v1.20.5 diff --git a/order-go/Dockerfile b/order-go/Dockerfile new file mode 100644 index 0000000..a598945 --- /dev/null +++ b/order-go/Dockerfile @@ -0,0 +1,29 @@ +# Use official Golang image as builder +FROM golang:1.22 AS builder + +WORKDIR /app + +# Copy the Go modules manifest files +COPY go.mod go.sum ./ +RUN go mod download + +# Copy the source code +COPY . . + +# Build the application with static linking +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o order main.go +RUN make licenses-report + +# Use minimal image for deployment +FROM alpine:3.18 + +WORKDIR /root/ + +# Copy the binary from builder +COPY --from=builder /app/order . + +# Expose the application port +EXPOSE 8081 + +# Run the application +CMD ["./order"] \ No newline at end of file diff --git a/order-go/LICENSE b/order-go/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/order-go/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/order-go/Makefile b/order-go/Makefile new file mode 100644 index 0000000..77e145a --- /dev/null +++ b/order-go/Makefile @@ -0,0 +1,25 @@ +build: + go build -o order main.go + +run: + go run main.go + +docker-build: + docker build -t order . + +docker-run: + docker run -p 8086:8086 order + +## licenses-report: generate a report of all licenses +.PHONY: licenses-report +licenses-report: +ifeq ($(SKIP_LICENSES_REPORT), true) + @echo "Skipping licenses report" + rm -rf ./licenses && mkdir -p ./licenses +else + @echo "Generating licenses report" + rm -rf ./licenses + go run github.com/google/go-licenses@v1.6.0 save . --save_path ./licenses + go run github.com/google/go-licenses@v1.6.0 report . > ./licenses/THIRD-PARTY.csv + cp LICENSE ./licenses/LICENSE.txt +endif \ No newline at end of file diff --git a/order-go/go.mod b/order-go/go.mod new file mode 100644 index 0000000..aac4ddf --- /dev/null +++ b/order-go/go.mod @@ -0,0 +1,24 @@ +module order + +go 1.22 + +require ( + github.com/go-stomp/stomp/v3 v3.1.3 + github.com/prometheus/client_golang v1.20.5 + github.com/rs/zerolog v1.33.0 + github.com/steadybit/extension-kit v1.8.23 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + golang.org/x/sys v0.29.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect +) diff --git a/order-go/go.sum b/order-go/go.sum new file mode 100644 index 0000000..7a74cb3 --- /dev/null +++ b/order-go/go.sum @@ -0,0 +1,87 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +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/go-stomp/stomp/v3 v3.1.3 h1:5/wi+bI38O1Qkf2cc7Gjlw7N5beHMWB/BxpX+4p/MGI= +github.com/go-stomp/stomp/v3 v3.1.3/go.mod h1:ztzZej6T2W4Y6FlD+Tb5n7HQP3/O5UNQiuC169pIp10= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/steadybit/extension-kit v1.8.23 h1:YyHCP1cfETOmOX8Bn21n+E910IhbjQZIWoV4Eu9Ks28= +github.com/steadybit/extension-kit v1.8.23/go.mod h1:qUiOw0OJUkyuz9hkLkGfksc09JRkSyrKEiiIiuVc3+o= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +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/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/order-go/main.go b/order-go/main.go new file mode 100644 index 0000000..99046ac --- /dev/null +++ b/order-go/main.go @@ -0,0 +1,124 @@ +/* + * Copyright 2025 steadybit GmbH. All rights reserved. + */ + +package main + +import ( + "encoding/json" + stomp "github.com/go-stomp/stomp/v3" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/rs/zerolog/log" + "github.com/steadybit/extension-kit/extlogging" + "net/http" + "os" + "time" +) + +func healthHandler(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, err := w.Write([]byte("OK")) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + +func readinessHandler(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, err := w.Write([]byte("READY")) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + +type OrderItem struct { + ProductID string `json:"productId"` + Quantity int `json:"quantity"` + Price float64 `json:"price"` +} +type Order struct { + ID string `json:"id"` + Submitted string `json:"submitted"` + Items []OrderItem `json:"items"` +} + +func main() { + log.Info().Msg("Starting Order Application...") + extlogging.InitZeroLog() + + // Retrieve ActiveMQ connection info from environment variables (or use defaults). + brokerAddr, found := os.LookupEnv("ACTIVEMQ_BROKER_HOST") + if !found { + brokerAddr, found = os.LookupEnv("activemq.broker.host") + } + if !found { + brokerAddr = "localhost:61613" + } + user := os.Getenv("ACTIVEMQ_USER") + pass := os.Getenv("ACTIVEMQ_PASS") + + // 1) Connect to ActiveMQ using STOMP. + var conn *stomp.Conn + var err error + if user == "" { + conn, err = stomp.Dial("tcp", brokerAddr, stomp.ConnOpt.HeartBeat(5*time.Second, 5*time.Second)) + } else { + conn, err = stomp.Dial("tcp", brokerAddr, stomp.ConnOpt.Login(user, pass), stomp.ConnOpt.HeartBeat(5*time.Second, 5*time.Second)) + } + if err != nil { + log.Error().Err(err).Msg("Failed to connect to ActiveMQ") + } + defer func() { + if conn != nil { + _ = conn.Disconnect() + } + }() + + // 2) Subscribe to the "order_created" queue. (Equivalent of @JmsListener in Java.) + if conn == nil { + log.Error().Msg("Connection to ActiveMQ is nil") + return + } + sub, err := conn.Subscribe("order_created", stomp.AckAuto) + if err != nil { + log.Error().Err(err).Msg("Failed to subscribe to queue") + } + + // 3) Consume messages in a separate goroutine. + // Unmarshal into an Order object and log it. + go func() { + for { + msg := <-sub.C + if msg == nil { + continue + } + if msg.Err != nil { + log.Error().Err(msg.Err).Msg("Failed to receive message") + continue + } + if msg.Body == nil { + continue + } + var order Order + if err := json.Unmarshal(msg.Body, &order); err != nil { + log.Error().Err(err).Msg("Failed to unmarshal message") + continue + } + + log.Info().Str("orderID", order.ID).Msg("Received order") + } + }() + + http.Handle("/metrics", promhttp.Handler()) + + // Setup HTTP server + http.HandleFunc("/actuator/health/liveness", healthHandler) // Liveness Probe + http.HandleFunc("/actuator/health/readiness", readinessHandler) // Readiness Probe + port := "8086" + println("Server running on port:", port) + if err := http.ListenAndServe(":"+port, nil); err != nil { + panic(err) + } +}