Compare commits
42 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
842112359a | |
|
|
5183cac7fa | |
|
|
9238c74a21 | |
|
|
0e0f644421 | |
|
|
ee726fc674 | |
|
|
919f734f3b | |
|
|
8aae6a5153 | |
|
|
4660ea8377 | |
|
|
ff8c119779 | |
|
|
bdcc64166f | |
|
|
087e594b07 | |
|
|
9ab9604298 | |
|
|
762248fd55 | |
|
|
eef4e696af | |
|
|
c838c74bce | |
|
|
bd7bfc1494 | |
|
|
5aa9529113 | |
|
|
75deb16e43 | |
|
|
e944e5b014 | |
|
|
732d126c73 | |
|
|
5c6c1f6ebd | |
|
|
30d2f18396 | |
|
|
6f82fad6e4 | |
|
|
30a423c197 | |
|
|
f1447d8d6f | |
|
|
6326a80cca | |
|
|
a943fa2274 | |
|
|
933b93cffd | |
|
|
96f34f8e90 | |
|
|
4bd9f78e27 | |
|
|
1b8ce5ee12 | |
|
|
8b148c21da | |
|
|
d5a57af78f | |
|
|
b57c4f3ff8 | |
|
|
72ac3739b6 | |
|
|
af5e784234 | |
|
|
7bd2262ad6 | |
|
|
559229aede | |
|
|
ed7f24d1bd | |
|
|
522d814150 | |
|
|
ad6bd6b18e | |
|
|
cf18992b3a |
Binary file not shown.
|
|
@ -0,0 +1,58 @@
|
|||
apiVersion: v2
|
||||
actions:
|
||||
- name: "Deploy using helm"
|
||||
events:
|
||||
- name: "sh.keptn.event.deployment.triggered"
|
||||
tasks:
|
||||
- name: "Run helm"
|
||||
files:
|
||||
- /charts
|
||||
env:
|
||||
- name: IMAGE
|
||||
value: "$.data.configurationChange.values.image"
|
||||
valueFrom: event
|
||||
image: "alpine/helm:3.7.2"
|
||||
serviceAccount: "jes-deploy-using-helm"
|
||||
cmd: ["helm"]
|
||||
args: ["upgrade", "--create-namespace", "--install", "-n", "$(KEPTN_PROJECT)-$(KEPTN_STAGE)", "$(KEPTN_SERVICE)", "/keptn/charts/$(KEPTN_SERVICE).tgz", "--set", "image=$(IMAGE)", "--set", "keptn.service=$(KEPTN_SERVICE)", "--set", "keptn.deployment=$(KEPTN_STAGE)", "--wait"]
|
||||
|
||||
- name: "Rollback using helm"
|
||||
events:
|
||||
- name: "sh.keptn.event.rollback.triggered"
|
||||
tasks:
|
||||
- name: "Run helm"
|
||||
serviceAccount: "jes-deploy-using-helm"
|
||||
image: "alpine/helm:3.7.2"
|
||||
cmd: ["helm"]
|
||||
args: ["rollback", "-n", "$(KEPTN_PROJECT)-$(KEPTN_STAGE)", "$(KEPTN_SERVICE)", "--wait"]
|
||||
|
||||
- name: "Scale using kubectl"
|
||||
events:
|
||||
- name: "sh.keptn.event.action.triggered"
|
||||
jsonpath:
|
||||
property: "$.data.action.action"
|
||||
match: "scaling"
|
||||
tasks:
|
||||
- name: "Run kubectl"
|
||||
serviceAccount: "jes-deploy-using-helm"
|
||||
env:
|
||||
- name: SCALING
|
||||
value: $.data.action.value
|
||||
valueFrom: event
|
||||
image: "alpine/k8s:1.20.15"
|
||||
cmd: ["sh"]
|
||||
# Note: Hardcoded kubernetes namespace & KEPTN_SERVICE does most likely not match the deployment name
|
||||
args: ["-c", "REPLICAS=$(kubectl -n ${KEPTN_PROJECT}-${KEPTN_STAGE} get deployment/${KEPTN_SERVICE} -o go-template='{{.spec.replicas}}');DESIRED=$((${SCALING}+${REPLICAS}));echo Scaling deployment to ${DESIRED} && kubectl -n ${KEPTN_PROJECT}-${KEPTN_STAGE} scale --replicas=${DESIRED} deployment/${KEPTN_SERVICE}"]
|
||||
|
||||
- name: "Run tests using locust"
|
||||
events:
|
||||
- name: "sh.keptn.event.test.triggered"
|
||||
tasks:
|
||||
- name: "Run locust"
|
||||
files:
|
||||
- locust/basic.py
|
||||
- locust/locust.conf
|
||||
|
||||
image: "locustio/locust:2.8.6"
|
||||
cmd: ["locust"]
|
||||
args: ["--config", "/keptn/locust/locust.conf", "-f", "/keptn/locust/basic.py", "--host", "http://$(KEPTN_SERVICE).$(KEPTN_PROJECT)-$(KEPTN_STAGE)", "--only-summary"]
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
servicename: carts-db
|
||||
creationtimestamp: 2023-11-14 16:06:46.781502681 +0000 UTC
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: v1
|
||||
description: A Helm chart for service carts
|
||||
name: carts
|
||||
version: 0.1.0
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -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-dev.nttdata-xlabs.com</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">443</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="PROTOCOL" elementType="Argument">
|
||||
<stringProp name="Argument.name">PROTOCOL</stringProp>
|
||||
<stringProp name="Argument.value">https</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-dev.nttdata-xlabs.com</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">443</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="PROTOCOL" elementType="Argument">
|
||||
<stringProp name="Argument.name">PROTOCOL</stringProp>
|
||||
<stringProp name="Argument.value">https</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,58 @@
|
|||
apiVersion: v2
|
||||
actions:
|
||||
- name: "Deploy using helm"
|
||||
events:
|
||||
- name: "sh.keptn.event.deployment.triggered"
|
||||
tasks:
|
||||
- name: "Run helm"
|
||||
files:
|
||||
- /charts
|
||||
env:
|
||||
- name: IMAGE
|
||||
value: "$.data.configurationChange.values.image"
|
||||
valueFrom: event
|
||||
image: "alpine/helm:3.7.2"
|
||||
serviceAccount: "jes-deploy-using-helm"
|
||||
cmd: ["helm"]
|
||||
args: ["upgrade", "--force", "--create-namespace", "--install", "-n", "$(KEPTN_PROJECT)-$(KEPTN_STAGE)", "$(KEPTN_SERVICE)", "/keptn/charts/$(KEPTN_SERVICE).tgz", "--set", "image=$(IMAGE)", "--set", "keptn.service=$(KEPTN_SERVICE)", "--set", "keptn.deployment=$(KEPTN_STAGE)", "--set", "keptn.project=$(KEPTN_PROJECT)","--set", "keptn.stage=$(KEPTN_STAGE)", "--wait"]
|
||||
|
||||
- name: "Rollback using helm"
|
||||
events:
|
||||
- name: "sh.keptn.event.rollback.triggered"
|
||||
tasks:
|
||||
- name: "Run helm"
|
||||
serviceAccount: "jes-deploy-using-helm"
|
||||
image: "alpine/helm:3.7.2"
|
||||
cmd: ["helm"]
|
||||
args: ["rollback", "-n", "$(KEPTN_PROJECT)-$(KEPTN_STAGE)", "$(KEPTN_SERVICE)", "--wait"]
|
||||
|
||||
- name: "Scale using kubectl"
|
||||
events:
|
||||
- name: "sh.keptn.event.action.triggered"
|
||||
jsonpath:
|
||||
property: "$.data.action.action"
|
||||
match: "scaling"
|
||||
tasks:
|
||||
- name: "Run kubectl"
|
||||
serviceAccount: "jes-deploy-using-helm"
|
||||
env:
|
||||
- name: SCALING
|
||||
value: $.data.action.value
|
||||
valueFrom: event
|
||||
image: "alpine/k8s:1.20.15"
|
||||
cmd: ["sh"]
|
||||
# Note: Hardcoded kubernetes namespace & KEPTN_SERVICE does most likely not match the deployment name
|
||||
args: ["-c", "REPLICAS=$(kubectl -n ${KEPTN_PROJECT}-${KEPTN_STAGE} get deployment/${KEPTN_SERVICE} -o go-template='{{.spec.replicas}}');DESIRED=$((${SCALING}+${REPLICAS}));echo Scaling deployment to ${DESIRED} && kubectl -n ${KEPTN_PROJECT}-${KEPTN_STAGE} scale --replicas=${DESIRED} deployment/${KEPTN_SERVICE}"]
|
||||
|
||||
- name: "Run tests using locust"
|
||||
events:
|
||||
- name: "sh.keptn.event.test.triggered"
|
||||
tasks:
|
||||
- name: "Run locust"
|
||||
files:
|
||||
- locust/basic.py
|
||||
- locust/locust.conf
|
||||
|
||||
image: "locustio/locust:2.8.6"
|
||||
cmd: ["locust"]
|
||||
args: ["--config", "/keptn/locust/locust.conf", "-f", "/keptn/locust/basic.py", "--host", "http://$(KEPTN_SERVICE)-$(KEPTN_STAGE).nttdata-xlabs.com", "--only-summary"]
|
||||
Binary file not shown.
|
|
@ -0,0 +1,8 @@
|
|||
from locust import HttpUser, between, task
|
||||
|
||||
class WebsiteUser(HttpUser):
|
||||
#wait_time = between(5, 15)
|
||||
|
||||
@task
|
||||
def index(self):
|
||||
self.client.post("/carts/1/items", json= {"itemId":"03fef6ac-1896-4ce8-bd69-b798f85c6e0b","unitPrice":"99.99"}, headers={"x-dynatrace-test": "LSN=Test;"})
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
locustfile = /locust/locust.py
|
||||
headless = true
|
||||
users = 5
|
||||
run-time = 1m
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
spec_version: "0.1.1"
|
||||
comparison:
|
||||
aggregate_function: "avg"
|
||||
compare_with: "single_result"
|
||||
include_result_with_score: "pass"
|
||||
number_of_comparison_results: 1
|
||||
filter:
|
||||
objectives:
|
||||
- sli: "response_time_p95"
|
||||
key_sli: false
|
||||
pass: # pass if (relative change <= 10% AND absolute value is < 600ms)
|
||||
- criteria:
|
||||
- "<=+25%" # relative values require a prefixed sign (plus or minus)
|
||||
- "<600000" # absolute values only require a logical operator
|
||||
warning: # if the response time is below 800ms, the result should be a warning
|
||||
- criteria:
|
||||
- "<=800000"
|
||||
weight: 1
|
||||
# - sli: "rt_addToCart" # looking at a particular transaction
|
||||
# weight: 3 # business critical transaction
|
||||
# pass:
|
||||
# - criteria:
|
||||
# - "<=+20%" # Degradation-driven
|
||||
# - "<300000" # NFR-driven
|
||||
# warning:
|
||||
# - criteria:
|
||||
# - "<=+50%"
|
||||
# - "<=500000"
|
||||
- sli: "error_rate"
|
||||
pass:
|
||||
- criteria:
|
||||
- "<=+15%"
|
||||
- "<2"
|
||||
warning:
|
||||
- criteria:
|
||||
- "<10"
|
||||
- sli: "pg_heap_suspension"
|
||||
- sli: "pg_cpu_usage"
|
||||
total_score:
|
||||
pass: "90%"
|
||||
warning: "70%"
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue