first commit
commit
4a59d4bd2d
Binary file not shown.
|
|
@ -0,0 +1,4 @@
|
||||||
|
apiVersion: v1
|
||||||
|
description: A Helm chart for service carts
|
||||||
|
name: carts
|
||||||
|
version: 0.1.0
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
1. Get the application URL by running these commands:
|
||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if contains "NodePort" .Values.service.type }}
|
||||||
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "carts.fullname" . }})
|
||||||
|
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||||
|
echo http://$NODE_IP:$NODE_PORT
|
||||||
|
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||||
|
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||||
|
You can watch the status of by running 'kubectl get svc -w {{ template "carts.fullname" . }}'
|
||||||
|
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "carts.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||||
|
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||||
|
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||||
|
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "carts.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||||
|
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||||
|
kubectl port-forward $POD_NAME 8080:80
|
||||||
|
{{- end }}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
{{/* vim: set filetype=mustache: */}}
|
||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "carts.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
If release name contains chart name it will be used as a full name.
|
||||||
|
*/}}
|
||||||
|
{{- define "carts.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride -}}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||||
|
{{- if contains $name .Release.Name -}}
|
||||||
|
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create chart name and version as used by the chart label.
|
||||||
|
*/}}
|
||||||
|
{{- define "carts.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: carts-db-mongodata
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 100Mi
|
||||||
|
status: {}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: carts-db
|
||||||
|
labels:
|
||||||
|
app: carts-db
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: carts-db
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carts-db
|
||||||
|
deployment: carts-db
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: carts-db
|
||||||
|
image: mongo
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- containerPort: 27017
|
||||||
|
resources: {}
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data/db
|
||||||
|
name: carts-db-mongodata
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- name: carts-db-mongodata
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: carts-db-mongodata
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: carts-db
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: carts-db
|
||||||
|
port: 27017
|
||||||
|
targetPort: 27017
|
||||||
|
selector:
|
||||||
|
app: carts-db
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
generateName: app-keptn-notification-
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/hook: Sync
|
||||||
|
argocd.argoproj.io/hook-delete-policy: HookSucceeded
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: keptn-notification
|
||||||
|
image: agrimmer/alpine-curl-uuid-kubectl:latest
|
||||||
|
command: ["/bin/sh","-c"]
|
||||||
|
args: ['while [[ $(kubectl get rollout {{ .Values.keptn.service }}-{{ .Values.keptn.stage }} -n {{ .Values.keptn.project }}-{{ .Values.keptn.stage }} -o "jsonpath={..status.conditions[?(@.type==\"Progressing\")].reason}") == "ReplicaSetUpdated" ]]; do echo "waiting for rollout" && sleep 1; done; UUID=$(uuidgen); now=$(TZ=UTC date "+%FT%T.00Z"); curl -X POST -H "Content-Type: application/cloudevents+json" -H "x-token: ${KEPTN_API_TOKEN}" --insecure -d "{\"contenttype\": \"application/json\", \"data\": { \"project\": \"{{ .Values.keptn.project }}\", \"service\": \"{{ .Values.keptn.service }}\", \"stage\": \"{{ .Values.keptn.stage }}\", \"deploymentURILocal\": \"http://{{ .Values.keptn.service }}-canary.{{ .Values.keptn.project }}-{{ .Values.keptn.stage }}\", \"deploymentstrategy\": \"blue_green_service\", \"teststrategy\": \"performance\"}, \"id\": \"${UUID}\", \"source\": \"argo\", \"specversion\": \"0.2\", \"time\": \"${now}\", \"type\": \"sh.keptn.events.deployment-finished\", \"shkeptncontext\": \"${UUID}\"}" ${KEPTN_API_URL}/v1/event']
|
||||||
|
env:
|
||||||
|
- name: KEPTN_API_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: argo
|
||||||
|
key: KEPTN_API_URL
|
||||||
|
- name: KEPTN_API_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: argo
|
||||||
|
key: KEPTN_API_TOKEN
|
||||||
|
restartPolicy: Never
|
||||||
|
backoffLimit: 2
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Rollout
|
||||||
|
metadata:
|
||||||
|
name: {{ template "carts.fullname" . }}
|
||||||
|
labels:
|
||||||
|
app: {{ template "carts.name" . }}
|
||||||
|
chart: {{ template "carts.chart" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
heritage: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
revisionHistoryLimit: 3
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ template "carts.name" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
strategy:
|
||||||
|
blueGreen:
|
||||||
|
autoPromotionEnabled: false
|
||||||
|
activeService: {{ template "carts.name" . }}-primary
|
||||||
|
previewService: {{ template "carts.name" . }}-canary
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: {{ template "carts.name" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: DT_CUSTOM_PROP
|
||||||
|
value: "keptn_project={{ .Values.keptn.project }} keptn_service={{ .Values.keptn.service }} keptn_stage={{ .Values.keptn.stage }}"
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.name"
|
||||||
|
- name: DEPLOYMENT_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.labels['deployment']"
|
||||||
|
- name: CONTAINER_IMAGE
|
||||||
|
value: "{{ .Values.image }}"
|
||||||
|
- name: KEPTN_PROJECT
|
||||||
|
value: "{{ .Values.keptn.project }}"
|
||||||
|
- name: KEPTN_STAGE
|
||||||
|
value: "{{ .Values.keptn.stage }}"
|
||||||
|
- name: KEPTN_SERVICE
|
||||||
|
value: "{{ .Values.keptn.service }}"
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 15
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 15
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2048Mi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1024Mi
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ template "carts.name" . }}-primary
|
||||||
|
labels:
|
||||||
|
app: {{ template "carts.name" . }}
|
||||||
|
chart: {{ template "carts.chart" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
heritage: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: {{ template "carts.name" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ template "carts.name" . }}-canary
|
||||||
|
labels:
|
||||||
|
app: {{ template "carts.name" . }}
|
||||||
|
chart: {{ template "carts.chart" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
heritage: {{ .Release.Service }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: {{ template "carts.name" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: docker.io/keptnexamples/carts
|
||||||
|
tag: 0.13.1
|
||||||
|
pullPolicy: Always
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: LoadBalancer
|
||||||
|
port: 80
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
annotations: {}
|
||||||
|
# kubernetes.io/ingress.class: nginx
|
||||||
|
# kubernetes.io/tls-acme: "true"
|
||||||
|
path: /
|
||||||
|
hosts:
|
||||||
|
- chart-example.local
|
||||||
|
tls: []
|
||||||
|
# - secretName: chart-example-tls
|
||||||
|
# hosts:
|
||||||
|
# - chart-example.local
|
||||||
|
|
||||||
|
keptn:
|
||||||
|
project: sockshop
|
||||||
|
stage: production
|
||||||
|
service: carts
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,4 @@
|
||||||
|
apiVersion: v1
|
||||||
|
description: A Helm chart for service carts-db
|
||||||
|
name: carts-db
|
||||||
|
version: 0.1.0
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: carts-db-mongodata
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
status: {}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: carts-db
|
||||||
|
labels:
|
||||||
|
app: carts-db
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: carts-db
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carts-db
|
||||||
|
deployment: carts-db
|
||||||
|
app.kubernetes.io/name: {{ .Values.keptn.service }}
|
||||||
|
app.kubernetes.io/instance: "{{ .Values.keptn.service }}-{{ .Values.keptn.deployment }}"
|
||||||
|
app.kubernetes.io/component: database
|
||||||
|
app.kubernetes.io/part-of: "{{ .Values.keptn.project }}"
|
||||||
|
app.kubernetes.io/managed-by: Keptn
|
||||||
|
app.kubernetes.io/version: {{ (split ":" .Values.image)._1 | default "latest" }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: carts-db
|
||||||
|
image: {{ .Values.image }}
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- containerPort: 27017
|
||||||
|
resources: {}
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data/db
|
||||||
|
name: carts-db-mongodata
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- name: carts-db-mongodata
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: carts-db-mongodata
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: carts-db
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: {{ .Values.service.name }}
|
||||||
|
port: {{ .Values.service.externalPort }}
|
||||||
|
targetPort: {{ .Values.service.internalPort }}
|
||||||
|
selector:
|
||||||
|
app: carts-db
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
image: mongo
|
||||||
|
service:
|
||||||
|
externalPort: 27017
|
||||||
|
internalPort: 27017
|
||||||
|
name: carts-db
|
||||||
|
replicaCount: 1
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
apiVersion: v1
|
||||||
|
description: A Helm chart for service carts
|
||||||
|
name: carts
|
||||||
|
version: 0.1.0
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: carts
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 0
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: carts
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carts
|
||||||
|
app.kubernetes.io/name: {{ .Values.keptn.service }}
|
||||||
|
app.kubernetes.io/instance: "{{ .Values.keptn.service }}-{{ .Values.keptn.deployment }}"
|
||||||
|
app.kubernetes.io/component: api
|
||||||
|
app.kubernetes.io/part-of: "{{ .Values.keptn.project }}"
|
||||||
|
app.kubernetes.io/managed-by: Keptn
|
||||||
|
app.kubernetes.io/version: {{ (split ":" .Values.image)._1 | default "latest" }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: carts
|
||||||
|
image: "{{ .Values.image }}"
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
containerPort: 8080
|
||||||
|
env:
|
||||||
|
- name: DT_CUSTOM_PROP
|
||||||
|
value: "version={{ .Chart.Version }} revision={{ .Release.Revision }} releasename={{ .Release.Name }} keptn_project={{ .Values.keptn.project }} keptn_service={{ .Values.keptn.service }} keptn_stage={{ .Values.keptn.stage }} keptn_deployment={{ .Values.keptn.deployment }}"
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.name"
|
||||||
|
- name: DEPLOYMENT_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.labels['deployment']"
|
||||||
|
- name: CONTAINER_IMAGE
|
||||||
|
value: "{{ .Values.image }}"
|
||||||
|
- name: KEPTN_PROJECT
|
||||||
|
value: "{{ .Chart.Name }}"
|
||||||
|
- name: KEPTN_STAGE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.namespace"
|
||||||
|
- name: KEPTN_SERVICE
|
||||||
|
value: "carts"
|
||||||
|
- name: UNLEASH_SERVER_URL
|
||||||
|
value: "http://unleash.unleash-dev/api"
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 15
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 15
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2048Mi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1024Mi
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: carts
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 8080
|
||||||
|
selector:
|
||||||
|
app: carts
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
image: docker.io/keptnexamples/carts:0.13.1
|
||||||
|
replicaCount: 1
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
spec_version: '0.1.0'
|
||||||
|
dtCreds: dynatrace
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.1.1 r1855137">
|
||||||
|
<hashTree>
|
||||||
|
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Testing Sample NodeJs" enabled="true">
|
||||||
|
<stringProp name="TestPlan.comments"></stringProp>
|
||||||
|
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||||
|
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||||
|
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||||
|
<collectionProp name="Arguments.arguments">
|
||||||
|
<elementProp name="SERVER_URL" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">SERVER_URL</stringProp>
|
||||||
|
<stringProp name="Argument.value">carts.sockshop-staging.public.demo.keptn.sh</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="CHECK_PATH" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">CHECK_PATH</stringProp>
|
||||||
|
<stringProp name="Argument.value">/</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="DT_LTN" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">DT_LTN</stringProp>
|
||||||
|
<stringProp name="Argument.value">Default</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="DefaultThinkTime" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">DefaultThinkTime</stringProp>
|
||||||
|
<stringProp name="Argument.value">250</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="SERVER_PORT" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">SERVER_PORT</stringProp>
|
||||||
|
<stringProp name="Argument.value">80</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="PROTOCOL" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">PROTOCOL</stringProp>
|
||||||
|
<stringProp name="Argument.value">http</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="VUCount" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">VUCount</stringProp>
|
||||||
|
<stringProp name="Argument.value">1</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="LoopCount" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">LoopCount</stringProp>
|
||||||
|
<stringProp name="Argument.value">1</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
</collectionProp>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||||
|
</TestPlan>
|
||||||
|
<hashTree>
|
||||||
|
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="BasicThreadGroup" enabled="true">
|
||||||
|
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||||
|
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||||
|
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||||
|
<stringProp name="LoopController.loops">${__P(LoopCount,${VUCount})}</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="ThreadGroup.num_threads">${__P(VUCount,${VUCount})}</stringProp>
|
||||||
|
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
|
||||||
|
<longProp name="ThreadGroup.start_time">1444323045000</longProp>
|
||||||
|
<longProp name="ThreadGroup.end_time">1444323045000</longProp>
|
||||||
|
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||||
|
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||||
|
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||||
|
</ThreadGroup>
|
||||||
|
<hashTree>
|
||||||
|
<CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
|
||||||
|
<collectionProp name="CookieManager.cookies"/>
|
||||||
|
<boolProp name="CookieManager.clearEachIteration">false</boolProp>
|
||||||
|
</CookieManager>
|
||||||
|
<hashTree/>
|
||||||
|
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||||
|
<collectionProp name="HeaderManager.headers"/>
|
||||||
|
</HeaderManager>
|
||||||
|
<hashTree/>
|
||||||
|
<BeanShellPreProcessor guiclass="TestBeanGUI" testclass="BeanShellPreProcessor" testname="Set Dynatrace Headers" enabled="true">
|
||||||
|
<boolProp name="resetInterpreter">true</boolProp>
|
||||||
|
<stringProp name="parameters"></stringProp>
|
||||||
|
<stringProp name="filename"></stringProp>
|
||||||
|
<stringProp name="script">import org.apache.jmeter.util.JMeterUtils;
|
||||||
|
import org.apache.jmeter.protocol.http.control.HeaderManager;
|
||||||
|
import java.io;
|
||||||
|
import java.util;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------
|
||||||
|
// Generate the x-dynatrace-test header based on this best practic
|
||||||
|
// -> https://www.dynatrace.com/support/help/integrations/test-automation-frameworks/how-do-i-integrate-dynatrace-into-my-load-testing-process/
|
||||||
|
// -------------------------------------------------------------------------------------
|
||||||
|
String LTN=JMeterUtils.getProperty("DT_LTN");
|
||||||
|
if((LTN == null) || (LTN.length() == 0)) {
|
||||||
|
if(vars != null) {
|
||||||
|
LTN = vars.get("DT_LTN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(LTN == null) LTN = "NoTestName";
|
||||||
|
|
||||||
|
String LSN = (bsh.args.length > 0) ? bsh.args[0] : "Test Scenario";
|
||||||
|
String TSN = sampler.getName();
|
||||||
|
String VU = ctx.getThreadGroup().getName() + ctx.getThreadNum();
|
||||||
|
String headerValue = "LSN="+ LSN + ";TSN=" + TSN + ";LTN=" + LTN + ";VU=" + VU + ";";
|
||||||
|
|
||||||
|
// -------------------------------------------
|
||||||
|
// Set header
|
||||||
|
// -------------------------------------------
|
||||||
|
HeaderManager hm = sampler.getHeaderManager();
|
||||||
|
hm.removeHeaderNamed("x-dynatrace-test");
|
||||||
|
hm.add(new org.apache.jmeter.protocol.http.control.Header("x-dynatrace-test", headerValue));</stringProp>
|
||||||
|
</BeanShellPreProcessor>
|
||||||
|
<hashTree/>
|
||||||
|
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Basic Check" enabled="true">
|
||||||
|
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true">
|
||||||
|
<collectionProp name="Arguments.arguments"/>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="HTTPSampler.domain">${__P(SERVER_URL,${SERVER_URL})}</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.port">${__P(SERVER_PORT,${SERVER_PORT})}</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.protocol">${__P(PROTOCOL,${PROTOCOL})}</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.path">${__P(CHECK_PATH,${CHECK_PATH})}</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||||
|
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||||
|
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||||
|
</HTTPSamplerProxy>
|
||||||
|
<hashTree>
|
||||||
|
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||||
|
<collectionProp name="HeaderManager.headers"/>
|
||||||
|
</HeaderManager>
|
||||||
|
<hashTree/>
|
||||||
|
</hashTree>
|
||||||
|
<ConstantTimer guiclass="ConstantTimerGui" testclass="ConstantTimer" testname="Default Think Time" enabled="true">
|
||||||
|
<stringProp name="ConstantTimer.delay">{__P(ThinkTime,${DefaultThinkTime})}</stringProp>
|
||||||
|
</ConstantTimer>
|
||||||
|
<hashTree/>
|
||||||
|
</hashTree>
|
||||||
|
<ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true">
|
||||||
|
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||||
|
<objProp>
|
||||||
|
<name>saveConfig</name>
|
||||||
|
<value class="SampleSaveConfiguration">
|
||||||
|
<time>true</time>
|
||||||
|
<latency>true</latency>
|
||||||
|
<timestamp>true</timestamp>
|
||||||
|
<success>true</success>
|
||||||
|
<label>true</label>
|
||||||
|
<code>true</code>
|
||||||
|
<message>true</message>
|
||||||
|
<threadName>true</threadName>
|
||||||
|
<dataType>true</dataType>
|
||||||
|
<encoding>false</encoding>
|
||||||
|
<assertions>true</assertions>
|
||||||
|
<subresults>true</subresults>
|
||||||
|
<responseData>false</responseData>
|
||||||
|
<samplerData>false</samplerData>
|
||||||
|
<xml>false</xml>
|
||||||
|
<fieldNames>false</fieldNames>
|
||||||
|
<responseHeaders>false</responseHeaders>
|
||||||
|
<requestHeaders>false</requestHeaders>
|
||||||
|
<responseDataOnError>false</responseDataOnError>
|
||||||
|
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
|
||||||
|
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||||
|
<bytes>true</bytes>
|
||||||
|
<threadCounts>true</threadCounts>
|
||||||
|
</value>
|
||||||
|
</objProp>
|
||||||
|
<stringProp name="filename"></stringProp>
|
||||||
|
</ResultCollector>
|
||||||
|
<hashTree/>
|
||||||
|
</hashTree>
|
||||||
|
</hashTree>
|
||||||
|
</jmeterTestPlan>
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.1.1 r1855137">
|
||||||
|
<hashTree>
|
||||||
|
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
||||||
|
<stringProp name="TestPlan.comments"></stringProp>
|
||||||
|
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||||
|
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||||
|
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||||
|
<collectionProp name="Arguments.arguments">
|
||||||
|
<elementProp name="SERVER_URL" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">SERVER_URL</stringProp>
|
||||||
|
<stringProp name="Argument.value">carts.sockshop-staging.public.demo.keptn.sh</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="DefaultThinkTime" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">DefaultThinkTime</stringProp>
|
||||||
|
<stringProp name="Argument.value">250</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="DT_LTN" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">DT_LTN</stringProp>
|
||||||
|
<stringProp name="Argument.value">Default</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="SERVER_PORT" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">SERVER_PORT</stringProp>
|
||||||
|
<stringProp name="Argument.value">80</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="PROTOCOL" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">PROTOCOL</stringProp>
|
||||||
|
<stringProp name="Argument.value">http</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="VUCount" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">VUCount</stringProp>
|
||||||
|
<stringProp name="Argument.value">1</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="LoopCount" elementType="Argument">
|
||||||
|
<stringProp name="Argument.name">LoopCount</stringProp>
|
||||||
|
<stringProp name="Argument.value">1</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
</collectionProp>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||||
|
</TestPlan>
|
||||||
|
<hashTree>
|
||||||
|
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
|
||||||
|
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||||
|
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||||
|
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||||
|
<stringProp name="LoopController.loops">${__P(LoopCount,${LoopCount})}</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="ThreadGroup.num_threads">${__P(VUCount,${VUCount})}</stringProp>
|
||||||
|
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
|
||||||
|
<longProp name="ThreadGroup.start_time">1536064517000</longProp>
|
||||||
|
<longProp name="ThreadGroup.end_time">1536064517000</longProp>
|
||||||
|
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||||
|
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||||
|
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||||
|
</ThreadGroup>
|
||||||
|
<hashTree>
|
||||||
|
<CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
|
||||||
|
<collectionProp name="CookieManager.cookies"/>
|
||||||
|
<boolProp name="CookieManager.clearEachIteration">false</boolProp>
|
||||||
|
</CookieManager>
|
||||||
|
<hashTree/>
|
||||||
|
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||||
|
<collectionProp name="HeaderManager.headers">
|
||||||
|
<elementProp name="" elementType="Header">
|
||||||
|
<stringProp name="Header.name">Cache-Control</stringProp>
|
||||||
|
<stringProp name="Header.value">no-cache</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="" elementType="Header">
|
||||||
|
<stringProp name="Header.name">Content-Type</stringProp>
|
||||||
|
<stringProp name="Header.value">application/json</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
<elementProp name="" elementType="Header">
|
||||||
|
<stringProp name="Header.name">json</stringProp>
|
||||||
|
<stringProp name="Header.value">true</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
</collectionProp>
|
||||||
|
</HeaderManager>
|
||||||
|
<hashTree/>
|
||||||
|
<BeanShellPreProcessor guiclass="TestBeanGUI" testclass="BeanShellPreProcessor" testname="Set Dynatrace Headers" enabled="true">
|
||||||
|
<stringProp name="filename"></stringProp>
|
||||||
|
<stringProp name="parameters"></stringProp>
|
||||||
|
<boolProp name="resetInterpreter">false</boolProp>
|
||||||
|
<stringProp name="script">import org.apache.jmeter.util.JMeterUtils;
|
||||||
|
import org.apache.jmeter.protocol.http.control.HeaderManager;
|
||||||
|
import java.io;
|
||||||
|
import java.util;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------
|
||||||
|
// Generate the x-dynatrace-test header based on this best practic
|
||||||
|
// -> https://www.dynatrace.com/support/help/integrations/test-automation-frameworks/how-do-i-integrate-dynatrace-into-my-load-testing-process/
|
||||||
|
// -------------------------------------------------------------------------------------
|
||||||
|
String LTN=JMeterUtils.getProperty("DT_LTN");
|
||||||
|
if((LTN == null) || (LTN.length() == 0)) {
|
||||||
|
if(vars != null) {
|
||||||
|
LTN = vars.get("DT_LTN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(LTN == null) LTN = "NoTestName";
|
||||||
|
|
||||||
|
String LSN = (bsh.args.length > 0) ? bsh.args[0] : "Test Scenario";
|
||||||
|
String TSN = sampler.getName();
|
||||||
|
String VU = ctx.getThreadGroup().getName() + ctx.getThreadNum();
|
||||||
|
String headerValue = "LSN="+ LSN + ";TSN=" + TSN + ";LTN=" + LTN + ";VU=" + VU + ";";
|
||||||
|
|
||||||
|
// -------------------------------------------
|
||||||
|
// Set header
|
||||||
|
// -------------------------------------------
|
||||||
|
HeaderManager hm = sampler.getHeaderManager();
|
||||||
|
hm.removeHeaderNamed("x-dynatrace-test");
|
||||||
|
hm.add(new org.apache.jmeter.protocol.http.control.Header("x-dynatrace-test", headerValue));</stringProp>
|
||||||
|
</BeanShellPreProcessor>
|
||||||
|
<hashTree/>
|
||||||
|
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Item to Cart" enabled="true">
|
||||||
|
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
|
||||||
|
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
|
||||||
|
<collectionProp name="Arguments.arguments">
|
||||||
|
<elementProp name="" elementType="HTTPArgument">
|
||||||
|
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||||
|
<stringProp name="Argument.value"> {
|
||||||
|
"itemId":"03fef6ac-1896-4ce8-bd69-b798f85c6e0b",
|
||||||
|
"unitPrice":"99.99"
|
||||||
|
}</stringProp>
|
||||||
|
<stringProp name="Argument.metadata">=</stringProp>
|
||||||
|
</elementProp>
|
||||||
|
</collectionProp>
|
||||||
|
</elementProp>
|
||||||
|
<stringProp name="HTTPSampler.domain">${__P(SERVER_URL,${SERVER_URL})}</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.port">${__P(SERVER_PORT,${SERVER_PORT})}</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.protocol">${__P(PROTOCOL,${PROTOCOL})}</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.path">/carts/1/items</stringProp>
|
||||||
|
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||||
|
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||||
|
<boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp>
|
||||||
|
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||||
|
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||||
|
</HTTPSamplerProxy>
|
||||||
|
<hashTree/>
|
||||||
|
<ConstantTimer guiclass="ConstantTimerGui" testclass="ConstantTimer" testname="Default Think Time" enabled="true">
|
||||||
|
<stringProp name="ConstantTimer.delay">{__P(ThinkTime,${DefaultThinkTime})}</stringProp>
|
||||||
|
</ConstantTimer>
|
||||||
|
<hashTree/>
|
||||||
|
</hashTree>
|
||||||
|
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
|
||||||
|
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||||
|
<objProp>
|
||||||
|
<name>saveConfig</name>
|
||||||
|
<value class="SampleSaveConfiguration">
|
||||||
|
<time>true</time>
|
||||||
|
<latency>true</latency>
|
||||||
|
<timestamp>true</timestamp>
|
||||||
|
<success>true</success>
|
||||||
|
<label>true</label>
|
||||||
|
<code>true</code>
|
||||||
|
<message>true</message>
|
||||||
|
<threadName>true</threadName>
|
||||||
|
<dataType>true</dataType>
|
||||||
|
<encoding>false</encoding>
|
||||||
|
<assertions>true</assertions>
|
||||||
|
<subresults>true</subresults>
|
||||||
|
<responseData>false</responseData>
|
||||||
|
<samplerData>false</samplerData>
|
||||||
|
<xml>false</xml>
|
||||||
|
<fieldNames>false</fieldNames>
|
||||||
|
<responseHeaders>false</responseHeaders>
|
||||||
|
<requestHeaders>false</requestHeaders>
|
||||||
|
<responseDataOnError>false</responseDataOnError>
|
||||||
|
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
|
||||||
|
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||||
|
<bytes>true</bytes>
|
||||||
|
<threadCounts>true</threadCounts>
|
||||||
|
</value>
|
||||||
|
</objProp>
|
||||||
|
<stringProp name="filename"></stringProp>
|
||||||
|
</ResultCollector>
|
||||||
|
<hashTree/>
|
||||||
|
</hashTree>
|
||||||
|
</hashTree>
|
||||||
|
</jmeterTestPlan>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
sli-provider: dynatrace
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: lighthouse-config-sockshop
|
||||||
|
namespace: keptn
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
sli-provider: prometheus
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: lighthouse-config-sockshop
|
||||||
|
namespace: keptn
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: carts-db-mongodata
|
||||||
|
namespace: sockshop-hardening
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 100Mi
|
||||||
|
status: {}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: carts-db
|
||||||
|
namespace: sockshop-hardening
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: carts-db
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carts-db
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: mongo
|
||||||
|
name: carts-db
|
||||||
|
ports:
|
||||||
|
- containerPort: 27017
|
||||||
|
resources: {}
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data/db
|
||||||
|
name: carts-db-mongodata
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- name: carts-db-mongodata
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: carts-db-mongodata
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: carts-db
|
||||||
|
namespace: sockshop-hardening
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: "27017"
|
||||||
|
port: 27017
|
||||||
|
targetPort: 27017
|
||||||
|
selector:
|
||||||
|
app: carts-db
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: carts
|
||||||
|
namespace: sockshop-hardening
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: carts
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: carts
|
||||||
|
version: v1
|
||||||
|
deployment: carts
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: carts
|
||||||
|
image: docker.io/keptnexamples/carts:0.13.1
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+UseG1GC -Djava.security.egd=file:/dev/urandom
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.name"
|
||||||
|
- name: KUBERNETES_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.namespace"
|
||||||
|
- name: DEPLOYMENT_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: "metadata.labels['deployment']"
|
||||||
|
- name: CONTAINER_IMAGE
|
||||||
|
value: docker.io/keptnexamples/carts:0.13.1
|
||||||
|
- name: DT_CUSTOM_PROP
|
||||||
|
value: "keptn_stage=hardening keptn_project=sockshop keptn_service=carts"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1024Mi
|
||||||
|
requests:
|
||||||
|
cpu: 400m
|
||||||
|
memory: 768Mi
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /tmp
|
||||||
|
name: tmp-volume
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 15
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 15
|
||||||
|
volumes:
|
||||||
|
- name: tmp-volume
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
nodeSelector:
|
||||||
|
beta.kubernetes.io/os: linux
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: carts
|
||||||
|
labels:
|
||||||
|
app: carts
|
||||||
|
namespace: sockshop-hardening
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
selector:
|
||||||
|
app: carts
|
||||||
|
type: LoadBalancer
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
apiVersion: spec.keptn.sh/0.1.4
|
||||||
|
kind: Remediation
|
||||||
|
metadata:
|
||||||
|
name: carts-remediation
|
||||||
|
spec:
|
||||||
|
remediations:
|
||||||
|
- problemType: Response time degradation
|
||||||
|
actionsOnOpen:
|
||||||
|
- action: scaling
|
||||||
|
name: scaling
|
||||||
|
description: Scale up
|
||||||
|
value: "1"
|
||||||
|
- problemType: response_time_p90
|
||||||
|
actionsOnOpen:
|
||||||
|
- action: scaling
|
||||||
|
name: scaling
|
||||||
|
description: Scale up
|
||||||
|
value: "1"
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: spec.keptn.sh/0.1.4
|
||||||
|
kind: Remediation
|
||||||
|
metadata:
|
||||||
|
name: carts-remediation
|
||||||
|
spec:
|
||||||
|
remediations:
|
||||||
|
- problemType: Response time degradation
|
||||||
|
actionsOnOpen:
|
||||||
|
- action: toggle-feature
|
||||||
|
name: Toogle feature flag
|
||||||
|
description: Toogle feature flag EnableItemCache to ON
|
||||||
|
value:
|
||||||
|
EnableItemCache: "on"
|
||||||
|
- problemType: Failure rate increase
|
||||||
|
actionsOnOpen:
|
||||||
|
- action: toggle-feature
|
||||||
|
name: Toogle feature flag
|
||||||
|
description: Toogle feature flag EnablePromotion to OFF
|
||||||
|
value:
|
||||||
|
EnablePromotion: "off"
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
apiVersion: "spec.keptn.sh/0.2.2"
|
||||||
|
kind: "Shipyard"
|
||||||
|
metadata:
|
||||||
|
name: "shipyard-sockshop"
|
||||||
|
spec:
|
||||||
|
stages:
|
||||||
|
- name: "production"
|
||||||
|
sequences:
|
||||||
|
- name: "artifact-delivery"
|
||||||
|
tasks:
|
||||||
|
- name: "deployment"
|
||||||
|
properties:
|
||||||
|
deploymentstrategy: "blue_green_service"
|
||||||
|
- name: "test"
|
||||||
|
properties:
|
||||||
|
teststrategy: "performance"
|
||||||
|
- name: "evaluation"
|
||||||
|
- name: "release"
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
apiVersion: "spec.keptn.sh/0.2.2"
|
||||||
|
kind: "Shipyard"
|
||||||
|
metadata:
|
||||||
|
name: "shipyard-quality-gates"
|
||||||
|
spec:
|
||||||
|
stages:
|
||||||
|
- name: "hardening"
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
apiVersion: "spec.keptn.sh/0.2.2"
|
||||||
|
kind: "Shipyard"
|
||||||
|
metadata:
|
||||||
|
name: "shipyard-sockshop"
|
||||||
|
spec:
|
||||||
|
stages:
|
||||||
|
- name: "dev"
|
||||||
|
sequences:
|
||||||
|
- name: "delivery"
|
||||||
|
tasks:
|
||||||
|
- name: "deployment"
|
||||||
|
properties:
|
||||||
|
deploymentstrategy: "direct"
|
||||||
|
- name: "test"
|
||||||
|
properties:
|
||||||
|
teststrategy: "functional"
|
||||||
|
- name: "evaluation"
|
||||||
|
- name: "release"
|
||||||
|
- name: "delivery-direct"
|
||||||
|
tasks:
|
||||||
|
- name: "deployment"
|
||||||
|
properties:
|
||||||
|
deploymentstrategy: "direct"
|
||||||
|
- name: "release"
|
||||||
|
|
||||||
|
- name: "staging"
|
||||||
|
sequences:
|
||||||
|
- name: "delivery"
|
||||||
|
triggeredOn:
|
||||||
|
- event: "dev.delivery.finished"
|
||||||
|
tasks:
|
||||||
|
- name: "deployment"
|
||||||
|
properties:
|
||||||
|
deploymentstrategy: "blue_green_service"
|
||||||
|
- name: "test"
|
||||||
|
properties:
|
||||||
|
teststrategy: "performance"
|
||||||
|
- name: "evaluation"
|
||||||
|
- name: "release"
|
||||||
|
- name: "rollback"
|
||||||
|
triggeredOn:
|
||||||
|
- event: "staging.delivery.finished"
|
||||||
|
selector:
|
||||||
|
match:
|
||||||
|
result: "fail"
|
||||||
|
tasks:
|
||||||
|
- name: "rollback"
|
||||||
|
- name: "delivery-direct"
|
||||||
|
triggeredOn:
|
||||||
|
- event: "dev.delivery-direct.finished"
|
||||||
|
tasks:
|
||||||
|
- name: "deployment"
|
||||||
|
properties:
|
||||||
|
deploymentstrategy: "direct"
|
||||||
|
- name: "release"
|
||||||
|
|
||||||
|
- name: "production"
|
||||||
|
sequences:
|
||||||
|
- name: "delivery"
|
||||||
|
triggeredOn:
|
||||||
|
- event: "staging.delivery.finished"
|
||||||
|
tasks:
|
||||||
|
- name: "deployment"
|
||||||
|
properties:
|
||||||
|
deploymentstrategy: "blue_green_service"
|
||||||
|
- name: "release"
|
||||||
|
- name: "rollback"
|
||||||
|
triggeredOn:
|
||||||
|
- event: "production.delivery.finished"
|
||||||
|
selector:
|
||||||
|
match:
|
||||||
|
result: "fail"
|
||||||
|
tasks:
|
||||||
|
- name: "rollback"
|
||||||
|
- name: "delivery-direct"
|
||||||
|
triggeredOn:
|
||||||
|
- event: "staging.delivery-direct.finished"
|
||||||
|
tasks:
|
||||||
|
- name: "deployment"
|
||||||
|
properties:
|
||||||
|
deploymentstrategy: "direct"
|
||||||
|
- name: "release"
|
||||||
|
|
||||||
|
- name: "remediation"
|
||||||
|
triggeredOn:
|
||||||
|
- event: "production.remediation.finished"
|
||||||
|
selector:
|
||||||
|
match:
|
||||||
|
evaluation.result: "fail"
|
||||||
|
tasks:
|
||||||
|
- name: "get-action"
|
||||||
|
- name: "action"
|
||||||
|
- name: "evaluation"
|
||||||
|
triggeredAfter: "15m"
|
||||||
|
properties:
|
||||||
|
timeframe: "15m"
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
spec_version: '1.0'
|
||||||
|
indicators:
|
||||||
|
response_time_p50: histogram_quantile(0.5, sum by(le) (rate(http_response_time_milliseconds_bucket{handler="ItemsController.addToCart",job="$SERVICE-$PROJECT-$STAGE-canary"}[$DURATION_SECONDS])))
|
||||||
|
response_time_p90: histogram_quantile(0.9, sum by(le) (rate(http_response_time_milliseconds_bucket{handler="ItemsController.addToCart",job="$SERVICE-$PROJECT-$STAGE-canary"}[$DURATION_SECONDS])))
|
||||||
|
response_time_p95: histogram_quantile(0.95, sum by(le) (rate(http_response_time_milliseconds_bucket{handler="ItemsController.addToCart",job="$SERVICE-$PROJECT-$STAGE-canary"}[$DURATION_SECONDS])))
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
spec_version: '1.0'
|
||||||
|
indicators:
|
||||||
|
throughput: "metricSelector=builtin:service.requestCount.total:merge(\"dt.entity.service\"):sum&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE)"
|
||||||
|
error_rate: "metricSelector=builtin:service.errors.total.count:merge(\"dt.entity.service\"):avg&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE)"
|
||||||
|
response_time_p50: "metricSelector=builtin:service.response.time:merge(\"dt.entity.service\"):percentile(50)&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE)"
|
||||||
|
response_time_p90: "metricSelector=builtin:service.response.time:merge(\"dt.entity.service\"):percentile(90)&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE)"
|
||||||
|
response_time_p95: "metricSelector=builtin:service.response.time:merge(\"dt.entity.service\"):percentile(95)&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE)"
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
spec_version: '1.0'
|
||||||
|
indicators:
|
||||||
|
throughput: "metricSelector=builtin:service.requestCount.total:merge(\"dt.entity.service\"):sum&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE),tag(keptn_deployment:$DEPLOYMENT)"
|
||||||
|
error_rate: "metricSelector=builtin:service.errors.total.count:merge(\"dt.entity.service\"):avg&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE),tag(keptn_deployment:$DEPLOYMENT)"
|
||||||
|
response_time_p50: "metricSelector=builtin:service.response.time:merge(\"dt.entity.service\"):percentile(50)&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE),tag(keptn_deployment:$DEPLOYMENT)"
|
||||||
|
response_time_p90: "metricSelector=builtin:service.response.time:merge(\"dt.entity.service\"):percentile(90)&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE),tag(keptn_deployment:$DEPLOYMENT)"
|
||||||
|
response_time_p95: "metricSelector=builtin:service.response.time:merge(\"dt.entity.service\"):percentile(95)&entitySelector=type(SERVICE),tag(keptn_project:$PROJECT),tag(keptn_stage:$STAGE),tag(keptn_service:$SERVICE),tag(keptn_deployment:$DEPLOYMENT)"
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
spec_version: '1.0'
|
||||||
|
indicators:
|
||||||
|
response_time_p50: histogram_quantile(0.5, sum by(le) (rate(http_response_time_milliseconds_bucket{handler="ItemsController.addToCart",job="$SERVICE-$PROJECT-$STAGE-$DEPLOYMENT"}[$DURATION_SECONDS])))
|
||||||
|
response_time_p90: histogram_quantile(0.9, sum by(le) (rate(http_response_time_milliseconds_bucket{handler="ItemsController.addToCart",job="$SERVICE-$PROJECT-$STAGE-$DEPLOYMENT"}[$DURATION_SECONDS])))
|
||||||
|
response_time_p95: histogram_quantile(0.95, sum by(le) (rate(http_response_time_milliseconds_bucket{handler="ItemsController.addToCart",job="$SERVICE-$PROJECT-$STAGE-$DEPLOYMENT"}[$DURATION_SECONDS])))
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
spec_version: "1.0"
|
||||||
|
comparison:
|
||||||
|
aggregate_function: "avg"
|
||||||
|
compare_with: "single_result"
|
||||||
|
include_result_with_score: "pass"
|
||||||
|
number_of_comparison_results: 1
|
||||||
|
filter:
|
||||||
|
objectives:
|
||||||
|
- sli: "response_time_p95"
|
||||||
|
displayName: "Response time P95"
|
||||||
|
key_sli: false
|
||||||
|
pass: # pass if (relative change <= 10% AND absolute value is < 600ms)
|
||||||
|
- criteria:
|
||||||
|
- "<=+10%" # relative values require a prefixed sign (plus or minus)
|
||||||
|
- "<600" # absolute values only require a logical operator
|
||||||
|
warning: # if the response time is below 800ms, the result should be a warning
|
||||||
|
- criteria:
|
||||||
|
- "<=800"
|
||||||
|
weight: 1
|
||||||
|
total_score:
|
||||||
|
pass: "90%"
|
||||||
|
warning: "75%"
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
spec_version: "1.0"
|
||||||
|
comparison:
|
||||||
|
aggregate_function: "avg"
|
||||||
|
compare_with: "single_result"
|
||||||
|
include_result_with_score: "pass"
|
||||||
|
number_of_comparison_results: 1
|
||||||
|
filter:
|
||||||
|
objectives:
|
||||||
|
- sli: "response_time_p90"
|
||||||
|
displayName: "Response time P90"
|
||||||
|
key_sli: false
|
||||||
|
pass: # pass if (relative change <= 10% AND absolute value is < 1000)
|
||||||
|
- criteria:
|
||||||
|
- "<=+10%" # relative values require a prefixed sign (plus or minus)
|
||||||
|
- "<1000" # absolute values only require a logical operator
|
||||||
|
warning: # if the response time is below 1200ms, the result should be a warning
|
||||||
|
- criteria:
|
||||||
|
- "<=1200"
|
||||||
|
weight: 1
|
||||||
|
- sli: "problem_open"
|
||||||
|
displayName: "Problem open"
|
||||||
|
key_sli: true
|
||||||
|
pass:
|
||||||
|
- criteria:
|
||||||
|
- "=0"
|
||||||
|
weight: 1
|
||||||
|
total_score:
|
||||||
|
pass: "90%"
|
||||||
|
warning: "40%"
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
spec_version: "1.0"
|
||||||
|
comparison:
|
||||||
|
aggregate_function: "avg"
|
||||||
|
compare_with: "single_result"
|
||||||
|
include_result_with_score: "pass"
|
||||||
|
number_of_comparison_results: 1
|
||||||
|
filter:
|
||||||
|
objectives:
|
||||||
|
- sli: "response_time_p90"
|
||||||
|
displayName: "Response time P90"
|
||||||
|
key_sli: false
|
||||||
|
pass: # pass if (relative change <= 10% AND absolute value is < 1000)
|
||||||
|
- criteria:
|
||||||
|
- "<=+10%" # relative values require a prefixed sign (plus or minus)
|
||||||
|
- "<1000" # absolute values only require a logical operator
|
||||||
|
warning: # if the response time is below 1200ms, the result should be a warning
|
||||||
|
- criteria:
|
||||||
|
- "<=1200"
|
||||||
|
weight: 1
|
||||||
|
total_score:
|
||||||
|
pass: "90%"
|
||||||
|
warning: "40%"
|
||||||
Loading…
Reference in New Issue