Skip to content

Commit

Permalink
add example
Browse files Browse the repository at this point in the history
  • Loading branch information
danielbdias committed Jun 3, 2024
1 parent 321d1b1 commit 3fc3b12
Show file tree
Hide file tree
Showing 30 changed files with 6,903 additions and 3 deletions.
6 changes: 3 additions & 3 deletions docs/docs/ci-cd-automation/testkube-pipeline.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@ spec:

Execute the following command to create the test executor object in Testkube. Do not forget to provide the path to your Tracetest definition file using the `--file` argument, and also the following variables:

- `TRACETEST_TOKEN`: your [environment token](../concepts/environment-token.mdx).
- `TRACETEST_ENVIRONMENT`: your [environment id](../concepts/environments.mdx).
- `TRACETEST_ORGANIZATION`: your [organization id](../concepts/organizations.mdx).
- `TRACETEST_TOKEN`: your [environment token](/concepts/environment-token.mdx).
- `TRACETEST_ENVIRONMENT`: your [environment id](/concepts/environments.mdx).
- `TRACETEST_ORGANIZATION`: your [organization id](/concepts/organizations.mdx).

```bash
kubectl testkube create test --file my/file/location.yaml --type "tracetest/test" --name pokeshop-tracetest-test --variable TRACETEST_TOKEN=tracetest-token --variable TRACETEST_ENVIRONMENT=tracetest-environment-id --variable TRACETEST_ORGANIZATION=tracetest-organization-id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
36 changes: 36 additions & 0 deletions examples/tracetest-with-github-action-and-secrets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Running Tracetest with secrets on Github Actions

This example shows how you can run Tracetest injecting secrets in a Github Action pipeline.

We are testing an example Payment ecosystem with [Tracetest](https://tracetest.io/), through the main CI script can be seen on [run-trace-based-tests.yml](./githubworkflows/run-trace-based-tests.yml) that could be put under `.github/workflows` folder in your repository
This script executes a trace-based test that will call the user-facing API with basic auth (that is stored in a Github Secret) and validates if every internal service is properly working.

## Application to be tested

We are testing four APIs that work together to emulate a Payment system. There are 4 APIs:
- [Gateway API](./services/gateway-api): user-facing API that receives payment orders, protected with Basic Auth
- [Payment Executor API](./services/payment-executor-api): executes a payment order after analyzing the customer profile
- [Risk Analysis API](./services/risk-analysis-api): analyze user profile to understand its score
- [Wallet API](./services/wallet-api): retains data about the Wallet balance of each user

These APIs are instrumented with [OpenTelemetry SDKs](https://opentelemetry.io/docs/languages/) and send data to [Jaeger](https://www.jaegertracing.io/) via the [OTel Collector](https://opentelemetry.io/docs/collector/).

```mermaid
flowchart LR
Gateway["Gateway API"]
PaymentExecutor["Payment Executor API"]
RiskAnalysis["Risk Analysis API"]
Wallet["Wallet API"]
OTelCollector["OTel Collector"]
Jaeger
User
User -- calls --> Gateway
subgraph PaymentSystem
Gateway -- queries --> Wallet
Gateway -- perform order --> PaymentExecutor
PaymentExecutor -- queries --> RiskAnalysis
end
PaymentSystem -- send telemetry --> OTelCollector
OTelCollector --> Jaeger
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
services:
gateway-api:
build: ./services/gateway-api
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- API_PORT=10013
- OTEL_SERVICE_NAME=gateway-api
- OTEL_EXPORTER_GRPC_URL=http://otel-collector:4317
- WALLET_API_ENDPOINT=http://wallet:10010/wallet
- PAYMENT_EXECUTOR_API_ENDPOINT=http://payment-executor:10012/payment/execute
ports:
- 10013:10013
depends_on:
- otel-collector
- payment-executor
- wallet

payment-executor:
build: ./services/payment-executor-api
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- PAYMENT_EXECUTOR_API_PORT=10012
- OTEL_SERVICE_NAME=payment-executor-api
- OTEL_EXPORTER_HTTP_URL=http://otel-collector:4318/v1/traces
- RISK_ANALYSIS_URL=http://risk-analysis:10011/computeRisk
ports:
- 10012:10012
depends_on:
- otel-collector
- risk-analysis

risk-analysis:
build: ./services/risk-analysis-api
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- RISK_ANALYSIS_API_PORT=10011
- OTEL_SERVICE_NAME=risk-analysis-api
- OTEL_EXPORTER_GRPC_URL=otel-collector:4317
ports:
- 10011:10011
depends_on:
- otel-collector

wallet:
build: ./services/wallet-api
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- WALLET_API_PORT=10010
- OTEL_SERVICE_NAME=wallet-api
- OTEL_EXPORTER_GRPC_URL=http://otel-collector:4317
ports:
- 10010:10010
depends_on:
- otel-collector

tracetest-agent:
image: kubeshop/tracetest-agent:latest
environment:
TRACETEST_API_KEY: ${TRACETEST_API_KEY}
TRACETEST_MODE: verbose

postgres:
image: postgres:14
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
healthcheck:
test: pg_isready -U "$$POSTGRES_USER" -d "$$POSTGRES_DB"
interval: 1s
timeout: 5s
retries: 60

otel-collector:
image: otel/opentelemetry-collector-contrib:0.100.0
command:
- "--config"
- "/otel-local-config.yaml"
volumes:
- ./services/otel-collector/collector.config.yaml:/otel-local-config.yaml
depends_on:
- jaeger

jaeger:
image: jaegertracing/all-in-one:latest
restart: unless-stopped
ports:
- 16686:16686
environment:
- COLLECTOR_OTLP_ENABLED=true
healthcheck:
test: ["CMD", "wget", "--spider", "localhost:16686"]
interval: 1s
timeout: 3s
retries: 60
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Run trace-based tests

on:
# runs on every push to main
push:
branches: [main]

# allows run manually via Actions tab on Github
workflow_dispatch:

env:
TRACETEST_API_KEY: ${{secrets.TRACETEST_API_KEY}}

jobs:
run-trace-based-tests:
name: Run trace based tests for Payment Ecosystem
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Configure Tracetest CLI
uses: kubeshop/tracetest-github-action@v1
with:
token: ${{secrets.TRACETEST_CLI_TOKEN}}

- name: Run APIs locally with docker compose
run: |
docker-compose up -d
docker compose logs -f > /tmp/docker-log &
- name: Configure Tracing Backend
run: |
tracetest datastore apply --file ./tracing-backend.yaml
- name: Inject secrets as a variable set on Tracetest
run: |
cat << EOF > vars.yaml
type: VariableSet
spec:
id: tracetesting-vars
name: AuthKeys for test
description: Variables used in basic auth for my API
values:
- key: USER
value: admin
- key: PASSWORD
value: ${{secrets.API_SECRET_PASSWORD}}
type: secret
EOF
tracetest apply variableset --file ./vars.yaml
- name: Run trace-based tests
run: |
tracetest run test --vars tracetesting-vars --file ./trace-based-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM node:slim

WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install

COPY . .

CMD [ "npm", "run", "with-grpc-tracer" ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const express = require("express")
const basicAuth = require("express-basic-auth")
const axios = require("axios")
const config = require("./config")

const opentelemetry = require('@opentelemetry/api')

const app = express()
app.use(express.json())
app.use(basicAuth({
users: { 'admin': 'supersecret' }
}))

app.post("/executePaymentOrder", async (req, res) => {
const { walletId, yearsAsACustomer } = req.body

try {
const balance = await getWalletBalance(walletId)
const status = await executePayment(balance, yearsAsACustomer)

return res.send({ status })
} catch (error) {
const activeSpan = opentelemetry.trace.getActiveSpan()

activeSpan.recordException(error)
activeSpan.setStatus({ code: opentelemetry.SpanStatusCode.ERROR })

console.error(error.stack)
return res.status(500).send('internal error!')
}
})

app.listen(config.port, () => {
console.log(`Listening for requests on http://localhost:${config.port}`)
})

async function getWalletBalance(walletId) {
const axiosConfig = {
method: 'get',
url: config.walletAPIEndpoint + "/" + walletId,
headers: {
'Content-Type': 'application/json'
}
}

const response = await axios.request(axiosConfig)
return response.data.balance
}

async function executePayment(balance, age) {
const raw = JSON.stringify({
"amount": balance,
"age": age
})

const axiosConfig = {
method: 'post',
url: config.paymentExecutorAPIEndpoint,
headers: {
'Content-Type': 'application/json'
},
data: raw
}

const response = await axios.request(axiosConfig)
return response.data.status
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
port: process.env.API_PORT,
otelServiceName: process.env.OTEL_SERVICE_NAME,
otelExporterGrpcUrl: process.env.OTEL_EXPORTER_GRPC_URL,
walletAPIEndpoint: process.env.WALLET_API_ENDPOINT,
paymentExecutorAPIEndpoint: process.env.PAYMENT_EXECUTOR_API_ENDPOINT,
}
Loading

0 comments on commit 3fc3b12

Please sign in to comment.