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