diff --git a/.ci/broker-performance-test-suite/broker_attestation_test.jmx b/.ci/broker-performance-test-suite/broker_attestation_test.jmx
new file mode 100644
index 000000000..cab44b8c9
--- /dev/null
+++ b/.ci/broker-performance-test-suite/broker_attestation_test.jmx
@@ -0,0 +1,2925 @@
+
+
+
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+ xmeter_ip
+ ${__property(xmeter_ip,,)}
+ xmeter server ip
+ =
+
+
+ port
+ ${__property(port,,)}
+ xmeter service port
+ =
+
+
+ xmeter_user
+ ${__property(xmeter_user,,)}
+ =
+
+
+ xmeter_pwd
+ ${__property(xmeter_pwd,,)}
+ =
+
+
+ emqx_ip
+ ${__property(emqx_ip,,)}
+ =
+
+
+ emqx_private_ip1
+ ${__property(emqx_private_ip1,,)}
+ =
+
+
+ emqx_private_ip2
+ ${__property(emqx_private_ip2,,)}
+ =
+
+
+ emqx_private_ip3
+ ${__property(emqx_private_ip3,,)}
+ =
+
+
+ api_version
+ ${__property(api_version,,/api/v5)}
+ =
+
+
+ scripts_path
+ ${__property(scripts_path,,)}
+ performance scripts path
+ =
+
+
+ plugins_path
+ ${__property(plugins_path,,)}
+ =
+
+
+ report_file
+ ${__property(report_file,,)}
+ =
+
+
+ mysql_ip
+ ${__property(mysql_ip,,)}
+ =
+
+
+ pgsql_ip
+ ${__property(pgsql_ip,,)}
+ =
+
+
+ redis_ip
+ ${__property(redis_ip,,)}
+ =
+
+
+ mongo_ip
+ ${__property(mongo_ip,,)}
+ =
+
+
+ http_ip
+ ${__property(http_ip,,)}
+ =
+
+
+ users_number
+ ${__property(users_number,,80000)}
+ =
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ continue
+
+ false
+ 1
+
+ 1
+ 1
+ false
+
+
+ true
+
+
+
+
+
+ http://${emqx_ip}
+ admin
+ public
+
+
+
+
+ false
+
+
+
+
+
+
+ ${xmeter_ip}
+ ${port}
+ https
+
+
+ 6
+
+
+
+
+
+ true
+
+
+
+ false
+ {"password":"${xmeter_pwd}","email":"${xmeter_user}"}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/account/login/
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ userid
+ $..id
+ 1
+ err_userid
+
+
+
+ true
+ token
+ jwt:
+ Con
+ 1
+ false
+ 0
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/account/${userid}/api_key
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ api_key
+ $..apiKey
+ 1
+ err_api_key
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+ true
+
+
+
+ false
+ {"name":"dailytest-${__time(yyMMdd,)}","description":"","hostIps":["${emqx_private_ip1}","${emqx_private_ip2}","${emqx_private_ip3}"]}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/applications/${userid}
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+ applicationId
+ $..id
+ 1
+ err_id
+
+
+
+
+ ${__jexl3("${applicationId}"=="err_id",)}
+ false
+ true
+
+
+
+ true
+
+
+
+ false
+ {"name":"dailytest-${__time(yyMMdd,)}-${__Random(100,999,)}","description":"","hostIps":["${emqx_private_ip1}","${emqx_private_ip2}","${emqx_private_ip3}"]}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/applications/${userid}
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+ applicationId
+ $..id
+ 1
+ err_id
+
+
+
+
+
+ false
+ false
+
+
+
+
+
+
+ ${plugins_path}/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar
+ 0
+ application/java-archive
+
+
+
+
+
+
+ false
+ true
+ =
+ true
+ overwrite
+
+
+
+
+
+
+
+ /commercial_service/rest/dependency/plugins/upload
+ POST
+ true
+ false
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+ false
+ true
+
+
+
+ import redis.clients.jedis.Jedis;
+
+Jedis jedis = new Jedis("${redis_ip}",6379);
+
+//jedis.auth("");
+jedis.select(0);
+jedis.flushDB();
+jedis.hset("mqtt_user:emqx","password_hash","public");
+jedis.close();
+
+
+
+
+
+ false
+
+
+
+
+
+
+ ${scripts_path}/broker_connect.jmx
+ test_case
+ application/octet-stream
+
+
+
+
+
+
+ false
+ true
+ =
+ true
+ overwrite
+
+
+
+
+
+
+
+ /commercial_service/rest/api/fileupload
+ POST
+ true
+ false
+ true
+ true
+ true
+
+
+
+
+
+
+ test_id
+ $..testId
+ 1
+ err_test_id
+
+
+
+
+
+ xmeter-api-key
+ ${api_key}
+
+
+
+
+
+
+ true
+
+
+
+ false
+ {"server":"${redis_ip}:6379","salt_position":"prefix","redis_type":"single","database":0,"auto_reconnect":true,"password":"","password_hash_algorithm":"plain","pool_size":8,"cmd":"HMGET mqtt_user:${username} password_hash","ssl":{"enable":false},"backend":"redis","mechanism":"password-based"}
+ =
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/authentication
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 200
+
+
+ Assertion.response_code
+ false
+ 2
+
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/${test_id}/script_info
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ ramp_up
+ $.threadGroups[0].rampup
+ 1
+ err_rampup
+
+
+
+ 300
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+ true
+
+
+
+ false
+ {"testId":"${test_id}","vuNumber":${users_number},"executionDuration":-1,"loopCount":1,"rampupPeriod":${ramp_up},"variables":[{"description":"emqx server ip1","name":"emqx_ip1","value":"${emqx_private_ip1}"},{"name":"emqx_ip2","value":"${emqx_private_ip2}","description":"emqx server ip2"},{"name":"emqx_ip3","value":"${emqx_private_ip3}","description":"emqx server ip3"}],"distributions":[{"siteId":1,"value":${users_number},"tgUsers":[{"id":0,"number":${users_number},"threadGroupName":"Pub","throughputs":[]}]}],"dockerIpConfigEnabled":true,"applicationId":${applicationId},"clientTime":${__time(,)}}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/request
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ report_id
+ $..id
+ 1
+ err_report_id
+
+
+
+ https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}
+
+
+ false
+ import java.io.File;
+import java.io.FileWriter;
+
+FileWriter writer = new FileWriter("${report_file}", true);
+String content = "redis persist" + " " + "${__timeShift(yyyyMMdd HH:mm:ss,,,,)}" + " " + "https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}" + "\n";
+writer.write(content);
+writer.flush();
+writer.close();
+
+
+
+ 3000
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/nodes
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ count1;count2;count3
+ $.[0].connections;$.[1].connections;$.[2].connections
+ 1;1;1
+ err;0;0
+
+
+
+ int count = ${count1}+${count2}+${count3};
+ System.out.println(count);
+ if(count!=400000) {
+ Failure = true;
+ FailureMessage = "failed";
+ }else{
+ FailureMessage = "true";
+ }
+
+
+ false
+
+
+
+ 490000
+
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/authentication/password-based%3Aredis
+ DELETE
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 204
+
+
+ Assertion.response_code
+ false
+ 2
+
+
+
+ 100000
+
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/runningtests
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+ test_status
+ $..status
+ 1
+ err_test_status
+
+
+
+ test_id
+ $..id
+ 1
+ err_test_id
+
+
+
+
+ ${__jexl3("${test_status}"=="RUNNING",)}
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/testrun/stop/${test_id}
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+
+ 1
+ 0
+ 200000
+
+
+
+
+
+
+ false
+ true
+
+
+
+ false
+ true
+
+
+
+ true
+
+ 5000
+
+ mysql8
+ jdbc:mysql://${mysql_ip}:3306/mqtt
+ com.mysql.jdbc.Driver
+
+ true
+ public123
+ 0
+ false
+ 10000
+ DEFAULT
+ 60000
+ test
+
+
+
+ mysql8
+ Update Statement
+ CREATE TABLE IF NOT EXISTS `mqtt_user` (
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ `username` varchar(100) DEFAULT NULL,
+ `password_hash` varchar(100) DEFAULT NULL,
+ `salt` varchar(35) DEFAULT NULL,
+ `is_superuser` tinyint(1) DEFAULT 0,
+ `created` datetime DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `mqtt_username` (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+
+
+
+
+
+ Store as String
+
+
+
+
+ updates
+
+
+ Assertion.response_data
+ false
+ 16
+
+
+
+
+ mysql8
+ Update Statement
+ INSERT INTO `mqtt_user` ( `username`, `password_hash`, `salt`)
+VALUES
+ ('emqx', 'public', NULL);
+
+
+
+
+
+
+
+
+ Store as String
+
+
+
+
+ updates
+
+
+ Assertion.response_data
+ false
+ 16
+
+
+
+
+
+
+
+ ${scripts_path}/broker_connect.jmx
+ test_case
+ application/octet-stream
+
+
+
+
+
+
+ false
+ true
+ =
+ true
+ overwrite
+
+
+
+
+
+
+
+ /commercial_service/rest/api/fileupload
+ POST
+ true
+ false
+ true
+ true
+ true
+
+
+
+
+
+
+ test_id
+ $..testId
+ 1
+ err_test_id
+
+
+
+
+
+ xmeter-api-key
+ ${api_key}
+
+
+
+
+
+
+ true
+
+
+
+ false
+ {"server":"${mysql_ip}:3306","username":"test","password":"public123","database":"mqtt","pool_size":8,"auto_reconnect":true,"ssl":{"enable":false},"query":"SELECT password_hash FROM mqtt_user where username = ${username} LIMIT 1","password_hash_algorithm":"plain","salt_position":"prefix","query_timeout":"5s","backend":"mysql","mechanism":"password-based"}
+ =
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/authentication
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 200
+
+
+ Assertion.response_code
+ false
+ 2
+
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/${test_id}/script_info
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ ramp_up
+ $.threadGroups[0].rampup
+ 1
+ err_rampup
+
+
+
+ 300
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+ true
+
+
+
+ false
+ {"testId":"${test_id}","vuNumber":${users_number},"executionDuration":-1,"loopCount":1,"rampupPeriod":${ramp_up},"variables":[{"description":"emqx server ip1","name":"emqx_ip1","value":"${emqx_private_ip1}"},{"name":"emqx_ip2","value":"${emqx_private_ip2}","description":"emqx server ip2"},{"name":"emqx_ip3","value":"${emqx_private_ip3}","description":"emqx server ip3"}],"distributions":[{"siteId":1,"value":${users_number},"tgUsers":[{"id":0,"number":${users_number},"threadGroupName":"Pub","throughputs":[]}]}],"dockerIpConfigEnabled":true,"applicationId":${applicationId},"clientTime":${__time(,)}}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/request
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ report_id
+ $..id
+ 1
+ err_report_id
+
+
+
+ https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}
+
+
+ false
+ import java.io.File;
+import java.io.FileWriter;
+
+FileWriter writer = new FileWriter("${report_file}", true);
+String content = "mysql connect" + " " + "${__timeShift(yyyyMMdd HH:mm:ss,,,,)}" + " " + "https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}" + "\n";
+writer.write(content);
+writer.flush();
+writer.close();
+
+
+
+ 3000
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/nodes
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ count1;count2;count3
+ $.[0].connections;$.[1].connections;$.[2].connections
+ 1;1;1
+ err;0;0
+
+
+
+ int count = ${count1}+${count2}+${count3};
+ System.out.println(count);
+ if(count!=400000) {
+ Failure = true;
+ FailureMessage = "failed";
+ }else{
+ FailureMessage = "true";
+ }
+
+
+ false
+
+
+
+ 490000
+
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/authentication/password-based%3Amysql
+ DELETE
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 204
+
+
+ Assertion.response_code
+ false
+ 2
+
+
+
+ 100000
+
+
+
+
+ mysql8
+ Update Statement
+ DELETE FROM mqtt_user WHERE username = "emqx";
+
+
+
+
+
+
+ Store as String
+
+
+
+
+ 1
+
+
+ Assertion.response_data
+ false
+ 16
+
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/runningtests
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+ test_status
+ $..status
+ 1
+ err_test_status
+
+
+
+ test_id
+ $..id
+ 1
+ err_test_id
+
+
+
+
+ ${__jexl3("${test_status}"=="RUNNING",)}
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/testrun/stop/${test_id}
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+
+ 1
+ 0
+ 200000
+
+
+
+
+
+
+ false
+ true
+
+
+
+ false
+ true
+
+
+
+ groovy
+
+
+ true
+ import com.mongodb.*
+import com.gmongo.GMongoClient
+import com.mongodb.MongoCredential
+import com.mongodb.ServerAddress
+
+// disable user and pwd connect
+GMongoClient client = new GMongoClient(new ServerAddress("${mongo_ip}",27017))
+
+def DB=client.getDB("mqtt")
+//insert data
+def dataDB=DB.getCollection("mqtt_user").insert(["username" : "emqx", "password_hash" : "public", "is_superuser" : false, "salt": ""])
+String ReData=dataDB
+
+SampleResult.setResponseData(ReData)
+ disable account password connection
+
+
+
+
+
+
+ ${scripts_path}/broker_connect.jmx
+ test_case
+ application/octet-stream
+
+
+
+
+
+
+ false
+ true
+ =
+ true
+ overwrite
+
+
+
+
+
+
+
+ /commercial_service/rest/api/fileupload
+ POST
+ true
+ false
+ true
+ true
+ true
+
+
+
+
+
+
+ test_id
+ $..testId
+ 1
+ err_test_id
+
+
+
+
+
+ xmeter-api-key
+ ${api_key}
+
+
+
+
+
+
+ true
+
+
+
+ false
+ {"mongo_type":"single","server":"${mongo_ip}:27017","database":"mqtt","collection":"mqtt_user","selector":{"username":"${username}"},"password_hash_field":"password_hash","salt_field":"","password_hash_algorithm":"plain","salt_position":"prefix","pool_size":8,"ssl":{"enable":false},"topology":{"connect_timeout_ms":20000},"backend":"mongodb","mechanism":"password-based"}
+ =
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/authentication
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 200
+
+
+ Assertion.response_code
+ false
+ 2
+
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/${test_id}/script_info
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ ramp_up
+ $.threadGroups[0].rampup
+ 1
+ err_rampup
+
+
+
+ 300
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+ true
+
+
+
+ false
+ {"testId":"${test_id}","vuNumber":${users_number},"executionDuration":-1,"loopCount":1,"rampupPeriod":${ramp_up},"variables":[{"description":"emqx server ip1","name":"emqx_ip1","value":"${emqx_private_ip1}"},{"name":"emqx_ip2","value":"${emqx_private_ip2}","description":"emqx server ip2"},{"name":"emqx_ip3","value":"${emqx_private_ip3}","description":"emqx server ip3"}],"distributions":[{"siteId":1,"value":${users_number},"tgUsers":[{"id":0,"number":${users_number},"threadGroupName":"Pub","throughputs":[]}]}],"dockerIpConfigEnabled":true,"applicationId":${applicationId},"clientTime":${__time(,)}}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/request
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ report_id
+ $..id
+ 1
+ err_report_id
+
+
+
+ https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}
+
+
+ false
+ import java.io.File;
+import java.io.FileWriter;
+
+FileWriter writer = new FileWriter("${report_file}", true);
+String content = "mongo connect" + " " + "${__timeShift(yyyyMMdd HH:mm:ss,,,,)}" + " " + "https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}" + "\n";
+writer.write(content);
+writer.flush();
+writer.close();
+
+
+
+ 3000
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/nodes
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ count1;count2;count3
+ $.[0].connections;$.[1].connections;$.[2].connections
+ 1;1;1
+ err;0;0
+
+
+
+ int count = ${count1}+${count2}+${count3};
+ System.out.println(count);
+ if(count!=400000) {
+ Failure = true;
+ FailureMessage = "failed";
+ }else{
+ FailureMessage = "true";
+ }
+
+
+ false
+
+
+
+ 490000
+
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/authentication/password-based%3Amongodb
+ DELETE
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 204
+
+
+ Assertion.response_code
+ false
+ 2
+
+
+
+ 100000
+
+
+
+
+ groovy
+
+
+ true
+ import com.mongodb.*
+import com.gmongo.GMongoClient
+import com.mongodb.MongoCredential
+import com.mongodb.ServerAddress
+
+// disable user and pwd connect
+GMongoClient client = new GMongoClient(new ServerAddress("${mongo_ip}",27017))
+
+def DB=client.getDB("mqtt")
+//remove data
+def dataDB=DB.getCollection("mqtt_user").remove(["username" : "emqx", "password_hash" : "public", "is_superuser" : false, "salt": ""])
+String ReData=dataDB
+
+SampleResult.setResponseData(ReData)
+ disable account password connection
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/runningtests
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+ test_status
+ $..status
+ 1
+ err_test_status
+
+
+
+ test_id
+ $..id
+ 1
+ err_test_id
+
+
+
+
+ ${__jexl3("${test_status}"=="RUNNING",)}
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/testrun/stop/${test_id}
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+
+ 1
+ 0
+ 200000
+
+
+
+
+
+
+ false
+ true
+
+
+
+ false
+ true
+
+
+
+ true
+
+ 5000
+
+ pgsql
+ jdbc:postgresql://${pgsql_ip}:5432/mqtt
+ org.postgresql.Driver
+
+ true
+ public123
+ 0
+ false
+ 10000
+ DEFAULT
+ 60000
+ test
+
+
+
+ pgsql
+ Update Statement
+ CREATE TABLE IF NOT EXISTS mqtt_user (
+ id SERIAL primary key,
+ is_superuser boolean,
+ username character varying(100),
+ password_hash character varying(100),
+ salt character varying(40)
+);
+
+
+
+
+
+
+
+ Store as String
+
+
+
+
+ updates
+
+
+ Assertion.response_data
+ false
+ 16
+
+
+
+
+ pgsql
+ Update Statement
+ INSERT INTO mqtt_user (username, password_hash, salt, is_superuser)
+VALUES
+ ('emqx', 'public', NULL, false);
+
+
+
+
+
+
+
+ Store as String
+
+
+
+
+ updates
+
+
+ Assertion.response_data
+ false
+ 16
+
+
+
+
+
+
+
+ ${scripts_path}/pgsql_broker_connect.jmx
+ test_case
+ application/octet-stream
+
+
+
+
+
+
+ false
+ true
+ =
+ true
+ overwrite
+
+
+
+
+
+
+
+ /commercial_service/rest/api/fileupload
+ POST
+ true
+ false
+ true
+ true
+ true
+
+
+
+
+
+
+ test_id
+ $..testId
+ 1
+ err_test_id
+
+
+
+
+
+ xmeter-api-key
+ ${api_key}
+
+
+
+
+
+
+ true
+
+
+
+ false
+ {"server":"${pgsql_ip}:5432","username":"test","password":"public123","database":"mqtt","pool_size":8,"auto_reconnect":true,"ssl":{"enable":false},"query":"SELECT password_hash FROM mqtt_user where username = ${username} LIMIT 1","password_hash_algorithm":"plain","salt_position":"prefix","backend":"postgresql","mechanism":"password-based"}
+ =
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/authentication
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 200
+
+
+ Assertion.response_code
+ false
+ 2
+
+
+
+
+
+ false
+ true
+
+
+
+ true
+
+
+
+ false
+ {"testId":"${test_id}","vuNumber":10000,"executionDuration":-1,"loopCount":1,"variables":[{"description":"emqx server ip1","name":"emqx_ip1","value":"${emqx_private_ip1}"},{"name":"emqx_ip2","value":"${emqx_private_ip2}","description":"emqx server ip2"},{"name":"emqx_ip3","value":"${emqx_private_ip3}","description":"emqx server ip3"}],"distributions":[{"siteId":1,"value":10000,"tgUsers":[{"id":0,"number":10000,"threadGroupName":"Pub","throughputs":[]}]}],"dockerIpConfigEnabled":true,"applicationId":${applicationId},"clientTime":${__time(,)}}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/request
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ report_id
+ $..id
+ 1
+ err_report_id
+
+
+
+ https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}
+
+
+ false
+ import java.io.File;
+import java.io.FileWriter;
+
+FileWriter writer = new FileWriter("${report_file}", true);
+String content = "pgsql connect" + " " + "${__timeShift(yyyyMMdd HH:mm:ss,,,,)}" + " " + "https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}" + "\n";
+writer.write(content);
+writer.flush();
+writer.close();
+
+
+
+ 3000
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/nodes
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ count1;count2;count3
+ $.[0].connections;$.[1].connections;$.[2].connections
+ 1;1;1
+ err;0;0
+
+
+
+ int count = ${count1}+${count2}+${count3};
+ System.out.println(count);
+ if(count!=250000) {
+ Failure = true;
+ FailureMessage = "failed";
+ }else{
+ FailureMessage = "true";
+ }
+
+
+ false
+
+
+
+ 260000
+
+
+
+ count1
+ $..connections
+ 1
+ err
+
+
+
+ int count = ${count1};
+ System.out.println(count);
+ if(count!=50000) {
+ Failure = true;
+ FailureMessage = "failed";
+ }else{
+ FailureMessage = "true";
+ }
+
+
+ false
+
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/authentication/password-based%3Apostgresql
+ DELETE
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 204
+
+
+ Assertion.response_code
+ false
+ 2
+
+
+
+ 60000
+
+
+
+
+ pgsql
+ Update Statement
+ DELETE FROM mqtt_user WHERE username = 'emqx';
+
+
+
+
+
+
+ Store as String
+
+
+
+
+ 200
+
+
+ Assertion.response_code
+ false
+ 16
+
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/runningtests
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+ test_status
+ $..status
+ 1
+ err_test_status
+
+
+
+ test_id
+ $..id
+ 1
+ err_test_id
+
+
+
+
+ ${__jexl3("${test_status}"=="RUNNING",)}
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/testrun/stop/${test_id}
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+
+ 1
+ 0
+ 200000
+
+
+
+
+
+
+ false
+ true
+
+
+
+ false
+ true
+
+
+
+
+
+
+ ${scripts_path}/broker_mqtt_connect.jmx
+ test_case
+ application/octet-stream
+
+
+
+
+
+
+ false
+ true
+ =
+ true
+ overwrite
+
+
+
+
+
+
+
+ /commercial_service/rest/api/fileupload
+ POST
+ true
+ false
+ true
+ true
+ true
+
+
+
+
+
+
+ test_id
+ $..testId
+ 1
+ err_test_id
+
+
+
+
+
+ xmeter-api-key
+ ${api_key}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+ true
+
+
+
+ false
+ {"testId":"${test_id}","vuNumber":80000,"executionDuration":-1,"loopCount":1,"variables":[{"description":"emqx server ip1","name":"emqx_ip1","value":"${emqx_private_ip1}"},{"name":"emqx_ip2","value":"${emqx_private_ip2}","description":"emqx server ip2"},{"name":"emqx_ip3","value":"${emqx_private_ip3}","description":"emqx server ip3"}],"distributions":[{"siteId":1,"value":80000,"tgUsers":[{"id":0,"number":80000,"threadGroupName":"Pub","throughputs":[]}]}],"dockerIpConfigEnabled":true,"applicationId":${applicationId},"clientTime":${__time(,)}}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/request
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ report_id
+ $..id
+ 1
+ err_report_id
+
+
+
+ https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}
+
+
+ false
+ import java.io.File;
+import java.io.FileWriter;
+
+FileWriter writer = new FileWriter("${report_file}", true);
+String content = "connect mqtt test" + " " + "${__timeShift(yyyyMMdd HH:mm:ss,,,,)}" + " " + "https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}" + "\n";
+writer.write(content);
+writer.flush();
+writer.close();
+
+
+
+ 3000
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+
+
+
+ ${emqx_ip}
+ 18083
+ http
+
+ ${api_version}/nodes
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ 260000
+
+
+
+ count1;count2;count3
+ $.[0].connections;$.[1].connections;$.[2].connections
+ 1;1;1
+ err;0;0
+
+
+
+ int count = ${count1}+${count2}+${count3};
+ System.out.println(count);
+ if(count!=400000) {
+ Failure = true;
+ FailureMessage = "failed";
+ }else{
+ FailureMessage = "true";
+ }
+
+
+ false
+
+
+
+ count1
+ $..connections
+ 1
+ err
+
+
+
+ int count = ${count1};
+ System.out.println(count);
+ if(count!=250000) {
+ Failure = true;
+ FailureMessage = "failed";
+ }else{
+ FailureMessage = "true";
+ }
+
+
+ false
+
+
+
+
+ 1
+ 0
+ 60000
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/runningtests
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+ test_status
+ $..status
+ 1
+ err_test_status
+
+
+
+ test_id
+ $..id
+ 1
+ err_test_id
+
+
+
+
+ ${__jexl3("${test_status}"=="RUNNING",)}
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/testrun/stop/${test_id}
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+
+ 1
+ 0
+ 200000
+
+
+
+
+
+
+ false
+ true
+
+
+
+ false
+ true
+
+
+
+
+
+
+ ${scripts_path}/broker_pub_sub.jmx
+ test_case
+ application/octet-stream
+
+
+
+
+
+
+ false
+ true
+ =
+ true
+ overwrite
+
+
+
+
+
+
+
+ /commercial_service/rest/api/fileupload
+ POST
+ true
+ false
+ true
+ true
+ true
+
+
+
+
+
+
+ test_id
+ $..testId
+ 1
+ err_test_id
+
+
+
+
+
+ xmeter-api-key
+ ${api_key}
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+ true
+
+
+
+ false
+ {"testId":"${test_id}","vuNumber":80000,"executionDuration":-1,"loopCount":1,"replaceLoopToInfinite":false,"variables":[{"description":"emqx server ip1","name":"emqx_ip1","value":"${emqx_private_ip1}"},{"name":"emqx_ip2","value":"${emqx_private_ip2}","description":"emqx server ip2"},{"name":"emqx_ip3","value":"${emqx_private_ip3}","description":"emqx server ip3"}],"distributions":[{"siteId":1,"value":80000,"tgUsers":[{"id":0,"number":40000,"threadGroupName":"Sub","throughputs":[]},{"id":1,"number":40000,"threadGroupName":"Pub","throughputs":[]}]}],"dockerIpConfigEnabled":true,"applicationId":${applicationId},"clientTime":${__time(,)}}
+ =
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/request
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ report_id
+ $..id
+ 1
+ err_report_id
+
+
+
+ https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}
+
+
+ false
+ import java.io.File;
+import java.io.FileWriter;
+
+FileWriter writer = new FileWriter("${report_file}", true);
+String content = "mqtt pub&sub" + " " + "${__timeShift(yyyyMMdd HH:mm:ss,,,,)}" + " " + "https://${xmeter_ip}:${port}/commercialPage.html#/testrunMonitor/${report_id}" + "\n";
+writer.write(content);
+writer.flush();
+writer.close();
+
+
+
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+ xmeter-authorization
+ ${token}
+
+
+
+
+
+
+ 1
+ 0
+ 500000
+
+
+
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/${userid}/runningtests
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+ test_status
+ $..status
+ 1
+ err_test_status
+
+
+
+ test_id
+ $..id
+ 1
+ err_test_id
+
+
+
+
+ ${__jexl3("${test_status}"=="RUNNING",)}
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ /commercial_service/rest/testcase/testrun/stop/${test_id}
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ xmeter-authorization
+ ${token}
+
+
+ content-type
+ application/json;charset=utf-8
+
+
+ X-Requested-With
+ XMLHttpRequest
+
+
+
+
+
+
+ 1
+ 0
+ 200000
+
+
+
+
+
+
+
+
+
diff --git a/.ci/broker-performance-test-suite/broker_connect.jmx b/.ci/broker-performance-test-suite/broker_connect.jmx
new file mode 100644
index 000000000..8046ea4b5
--- /dev/null
+++ b/.ci/broker-performance-test-suite/broker_connect.jmx
@@ -0,0 +1,142 @@
+
+
+
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+ emqx_ip1
+ ${__property(emqx_ip1,,)}
+ emqx server ip
+ =
+
+
+ emqx_ip2
+ ${__property(emqx_ip2,,)}
+ =
+
+
+ emqx_ip3
+ ${__property(emqx_ip3,,)}
+ =
+
+
+ emqx_user
+ admin
+ emqx account
+ =
+
+
+ emqx_pwd
+ public
+ emqx password
+ =
+
+
+ mqtt_username
+ emqx
+ =
+
+
+ mqtt_password
+ public
+ =
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ continue
+
+ false
+ 1
+
+ 80000
+ 400
+ false
+
+
+ true
+
+
+
+ ${__RandomFromMultipleVars(emqx_ip1|emqx_ip2|emqx_ip3,)}
+ 1883
+ 3.1
+ 100
+ TCP
+
+ false
+
+
+ ${mqtt_username}
+ ${mqtt_password}
+
+ true
+ 300
+ 0
+ 0
+ true
+ false
+ 0
+
+ 5
+
+
+
+ 1
+ 0
+ 500000
+
+
+
+
+
+
diff --git a/.ci/broker-performance-test-suite/broker_mqtt_connect.jmx b/.ci/broker-performance-test-suite/broker_mqtt_connect.jmx
new file mode 100644
index 000000000..bc54c7c19
--- /dev/null
+++ b/.ci/broker-performance-test-suite/broker_mqtt_connect.jmx
@@ -0,0 +1,132 @@
+
+
+
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+ emqx_ip1
+ ${__property(emqx_ip1,,)}
+ emqx server ip
+ =
+
+
+ emqx_ip2
+ ${__property(emqx_ip2,,)}
+ =
+
+
+ emqx_ip3
+ ${__property(emqx_ip3,,)}
+ =
+
+
+ emqx_user
+ admin
+ emqx account
+ =
+
+
+ emqx_pwd
+ public
+ emqx password
+ =
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ continue
+
+ false
+ 1
+
+ 80000
+ 400
+ false
+
+
+ true
+
+
+
+ ${__RandomFromMultipleVars(emqx_ip1|emqx_ip2|emqx_ip3,)}
+ 1883
+ 3.1
+ 100
+ TCP
+
+ false
+
+
+
+
+
+ true
+ 300
+ 0
+ 0
+ true
+ false
+ 0
+
+ 5
+
+
+
+ 1
+ 0
+ 500000
+
+
+
+
+
+
diff --git a/.ci/broker-performance-test-suite/pgsql_broker_connect.jmx b/.ci/broker-performance-test-suite/pgsql_broker_connect.jmx
new file mode 100644
index 000000000..e6c1fe275
--- /dev/null
+++ b/.ci/broker-performance-test-suite/pgsql_broker_connect.jmx
@@ -0,0 +1,105 @@
+
+
+
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+ emqx_ip1
+ ${__property(emqx_ip1,,)}
+ emqx server ip
+ =
+
+
+ emqx_ip2
+ ${__property(emqx_ip2,,)}
+ =
+
+
+ emqx_ip3
+ ${__property(emqx_ip3,,)}
+ =
+
+
+ emqx_user
+ admin
+ emqx account
+ =
+
+
+ emqx_pwd
+ public
+ emqx password
+ =
+
+
+ mqtt_username
+ emqx
+ =
+
+
+ mqtt_password
+ public
+ =
+
+
+
+
+
+ continue
+
+ false
+ 1
+
+ 20000
+ 35
+ false
+
+
+ true
+
+
+
+ ${__RandomFromMultipleVars(emqx_ip1|emqx_ip2|emqx_ip3,)}
+ 1883
+ 3.1
+ 10
+ TCP
+
+ false
+
+
+ ${mqtt_username}
+ ${mqtt_password}
+
+ true
+ 300
+ 0
+ 0
+ true
+ false
+ 0
+
+ 1
+
+
+
+ 1
+ 0
+ 240000
+
+
+
+
+
+
diff --git a/.github/workflows/run_broker_performance_cluster.yaml b/.github/workflows/run_broker_performance_cluster.yaml
new file mode 100644
index 000000000..ad47acfd8
--- /dev/null
+++ b/.github/workflows/run_broker_performance_cluster.yaml
@@ -0,0 +1,470 @@
+name: Cluster Performance Test Suite
+
+concurrency:
+ group: slim-${{ github.event_name }}-${{ github.ref }}
+ cancel-in-progress: true
+
+on:
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: ubuntu-20.04
+
+ strategy:
+ fail-fast: false
+ matrix:
+ profile:
+ - emqx
+ otp:
+ - 23.3.4.9-3
+ os:
+ - ubuntu20.04
+
+ container: "ghcr.io/emqx/emqx-builder/5.0-2:${{ matrix.otp }}-${{ matrix.os }}"
+
+ steps:
+ - uses: actions/checkout@v1
+ - name: build zip packages
+ run: make ${{ matrix.profile }}-zip
+ - name: packages test
+ run: |
+ export CODE_PATH=$GITHUB_WORKSPACE
+ EMQX_NAME=${{ matrix.profile }} .ci/build_packages/tests.sh
+ - uses: actions/upload-artifact@v2
+ with:
+ name: ${{ matrix.os}}
+ path: _packages/**/*.zip
+
+ terraform_emqx:
+ runs-on: ubuntu-latest
+
+ needs: [build]
+ outputs:
+ emqx_public_ip: ${{ steps.emqx_private_ip.outputs.emqx_public_ip }}
+ emqx_node_ip1: ${{ steps.emqx_private_ip.outputs.emqx_node_ip1 }}
+ emqx_node_ip2: ${{ steps.emqx_private_ip.outputs.emqx_node_ip2 }}
+ emqx_node_ip3: ${{ steps.emqx_private_ip.outputs.emqx_node_ip3 }}
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/download-artifact@v2
+ with:
+ name: ubuntu20.04
+ path: /tmp
+ - name: Download emqx package
+ run: |
+ sudo cp /tmp/emqx/*.zip /tmp/emqx.zip
+ - name: Checkout tf-test-automation
+ uses: actions/checkout@v2
+ with:
+ repository: emqx/tf-test-automation
+ ref: emqx-broker
+ path: tf-test-automation
+ - name: Setup Terraform
+ uses: hashicorp/setup-terraform@v1.3.2
+ with:
+ terraform_wrapper: false
+ - name: Terraform Init tf-test-automation
+ working-directory: ./tf-test-automation/services/emqx
+ id: init1
+ run: |
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Validate tf-test-automation
+ working-directory: ./tf-test-automation/services/emqx
+ id: validate1
+ run: terraform validate -no-color
+ - name: Terraform Apply tf-test-automation
+ working-directory: ./tf-test-automation/services/emqx
+ id: server_ip
+ run: |
+ terraform apply -auto-approve -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}" -var="private_key=${{ secrets.CI_SSH_PRIVATE_KEY }}" -var="emqx_package=/tmp/emqx.zip"
+ echo "::set-output name=emqx_private_ips::$(terraform output emqx_private_ips)"
+ echo "::set-output name=emqx_public_ips::$(terraform output emqx_public_ips)"
+ - name: Rename and upload emqx tfstate
+ working-directory: ./tf-test-automation/services/emqx
+ run: |
+ mv ./terraform.tfstate ./emqx.tfstate
+ - uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: tfstate
+ path: ./tf-test-automation/services/emqx/emqx.tfstate
+ - name: Show emqx_private_ips
+ id: emqx_private_ip
+ run: |
+ ip1=`echo "${{ steps.server_ip.outputs.emqx_private_ips }}"|awk -F ',' '{print $1}'`
+ ip2=`echo "${{ steps.server_ip.outputs.emqx_private_ips }}"|awk -F ',' '{print $2}'`
+ ip3=`echo "${{ steps.server_ip.outputs.emqx_private_ips }}"|awk -F ',' '{print $3}'`
+ emqx_public_ip=`echo "${{ steps.server_ip.outputs.emqx_public_ips }}"|awk -F ',' '{print $1}'`
+ echo "::set-output name=emqx_node_ip1::$ip1"
+ echo "::set-output name=emqx_node_ip2::$ip2"
+ echo "::set-output name=emqx_node_ip3::$ip3"
+ echo "::set-output name=emqx_public_ip::$emqx_public_ip"
+ - name: Show emqx node ip
+ run: |
+ echo ${{ steps.emqx_private_ip.outputs.emqx_node_ip1 }}
+ echo ${{ steps.emqx_private_ip.outputs.emqx_node_ip2 }}
+ echo ${{ steps.emqx_private_ip.outputs.emqx_node_ip3 }}
+ echo ${{ steps.emqx_private_ip.outputs.emqx_public_ip }}
+
+ xmeter_start:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v1
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}
+ aws-region: ap-southeast-1
+ - name: Start Xmeter Services
+ run: |
+ aws ec2 start-instances --instance-ids i-0dd6d99916baaa1a8
+ aws ec2 start-instances --instance-ids i-05222103df01eb2d7
+ sleep 40;
+ aws ec2 start-instances --instance-ids i-0c5dccd394ed9be18
+ aws ec2 start-instances --instance-ids i-04c1c50b3e4952266
+
+ terraform_mysql:
+ runs-on: ubuntu-latest
+
+ outputs:
+ mysql_ip: ${{ steps.mysql_ip.outputs.mysql_ip }}
+ mysql_url: ${{ steps.mysql_url.outputs.mysql_url }}
+ steps:
+ - name: Checkout tf-test-automation
+ uses: actions/checkout@v2
+ with:
+ repository: emqx/tf-test-automation
+ ref: emqx-broker
+ path: tf-test-automation
+ - name: Setup Terraform
+ uses: hashicorp/setup-terraform@v1.3.2
+ with:
+ terraform_wrapper: false
+ - name: Terraform Init tf-test-automation
+ working-directory: ./tf-test-automation/services/mysql
+ id: init1
+ run: |
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Validate tf-test-automation
+ working-directory: ./tf-test-automation/services/mysql
+ id: validate1
+ run: terraform validate -no-color
+ - name: Terraform Apply tf-test-automation
+ working-directory: ./tf-test-automation/services/mysql
+ id: mysql_url
+ run: |
+ terraform apply -auto-approve -var="db_password=public123" -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ echo "::set-output name=mysql_url::$(terraform output endpoint)"
+ - name: Rename and upload mysql tfstate
+ working-directory: ./tf-test-automation/services/mysql
+ run: |
+ mv ./terraform.tfstate ./mysql.tfstate
+ - uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: tfstate
+ path: ./tf-test-automation/services/mysql/mysql.tfstate
+ - name: Show mysql url
+ id: mysql_ip
+ run: |
+ ip=`echo "${{ steps.mysql_url.outputs.mysql_url }}"|awk -F ':' '{print $1}'`
+ echo "::set-output name=mysql_ip::$ip"
+ - name: Show mysql ip
+ run: |
+ echo ${{ steps.mysql_url.outputs.mysql_url }}
+ echo ${{ steps.mysql_ip.outputs.mysql_ip }}
+#
+ terraform_redis:
+ runs-on: ubuntu-latest
+
+ outputs:
+ redis_ip: ${{ steps.redis_ip.outputs.redis_ip }}
+ steps:
+ - name: Checkout tf-test-automation
+ uses: actions/checkout@v2
+ with:
+ repository: emqx/tf-test-automation
+ ref: emqx-broker
+ path: tf-test-automation
+ - name: Setup Terraform
+ uses: hashicorp/setup-terraform@v1.3.2
+ with:
+ terraform_wrapper: false
+ - name: Terraform Init tf-test-automation
+ working-directory: ./tf-test-automation/services/redis
+ id: init
+ run: |
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Validate tf-test-automation
+ working-directory: ./tf-test-automation/services/redis
+ id: validate
+ run: terraform validate -no-color
+ - name: Terraform Apply tf-test-automation
+ working-directory: ./tf-test-automation/services/redis
+ id: redis_ip
+ run: |
+ terraform apply -auto-approve -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}" -var="private_key=${{ secrets.CI_SSH_PRIVATE_KEY }}"
+ echo "::set-output name=redis_ip::$(terraform output redis_private_ips)"
+ - name: Rename and upload redis server tfstate
+ working-directory: ./tf-test-automation/services/redis
+ run: |
+ mv ./terraform.tfstate ./redis.tfstate
+ - uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: tfstate
+ path: ./tf-test-automation/services/redis/redis.tfstate
+ - name: Show redis ip
+ run: |
+ echo ${{ steps.redis_ip.outputs.redis_ip }}
+
+ terraform_pgsql:
+ runs-on: ubuntu-latest
+
+ outputs:
+ pgsql_url: ${{ steps.pgsql_url.outputs.pgsql_url }}
+ pgsql_ip: ${{ steps.pgsql_ip.outputs.pgsql_ip }}
+ steps:
+ - name: Checkout tf-test-automation
+ uses: actions/checkout@v2
+ with:
+ repository: emqx/tf-test-automation
+ ref: emqx-broker
+ path: tf-test-automation
+ - name: Setup Terraform
+ uses: hashicorp/setup-terraform@v1.3.2
+ with:
+ terraform_wrapper: false
+ - name: Terraform Init tf-test-automation
+ working-directory: ./tf-test-automation/services/pgsql
+ id: init
+ run: |
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Validate tf-test-automation
+ working-directory: ./tf-test-automation/services/pgsql
+ id: validate
+ run: terraform validate -no-color
+ - name: Terraform Apply tf-test-automation
+ working-directory: ./tf-test-automation/services/pgsql
+ id: pgsql_url
+ run: |
+ terraform apply -auto-approve -var="db_password=public123" -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ echo "::set-output name=pgsql_url::$(terraform output endpoint)"
+ - name: Rename and upload pgsql server tfstate
+ working-directory: ./tf-test-automation/services/pgsql
+ run: |
+ mv ./terraform.tfstate ./pgsql.tfstate
+ - uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: tfstate
+ path: ./tf-test-automation/services/pgsql/pgsql.tfstate
+ - name: Show pgsql url
+ id: pgsql_ip
+ run: |
+ ip=`echo "${{ steps.pgsql_url.outputs.pgsql_url }}"|awk -F ':' '{print $1}'`
+ echo "::set-output name=pgsql_ip::$ip"
+ - name: Show pgsql ip
+ run: |
+ echo ${{ steps.pgsql_url.outputs.pgsql_url }}
+ echo ${{ steps.pgsql_ip.outputs.pgsql_ip }}
+
+ terraform_mongo:
+ runs-on: ubuntu-latest
+
+ outputs:
+ mongo_ip: ${{ steps.mongo_ip.outputs.mongo_ip }}
+ steps:
+ - name: Checkout tf-test-automation
+ uses: actions/checkout@v2
+ with:
+ repository: emqx/tf-test-automation
+ ref: emqx-broker
+ path: tf-test-automation
+ - name: Setup Terraform
+ uses: hashicorp/setup-terraform@v1.3.2
+ with:
+ terraform_wrapper: false
+ - name: Terraform Init tf-test-automation
+ working-directory: ./tf-test-automation/services/mongodb
+ id: init
+ run: |
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Validate tf-test-automation
+ working-directory: ./tf-test-automation/services/mongodb
+ id: validate
+ run: terraform validate -no-color
+ - name: Terraform Apply tf-test-automation
+ working-directory: ./tf-test-automation/services/mongodb
+ id: mongo_ip
+ run: |
+ terraform apply -auto-approve -var="db_password=public123" -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}" -var="private_key=${{ secrets.CI_SSH_PRIVATE_KEY }}"
+ echo "::set-output name=mongo_ip::$(terraform output mongo_private_ips)"
+ - name: Rename and upload mongo server tfstate
+ working-directory: ./tf-test-automation/services/mongodb
+ run: |
+ mv ./terraform.tfstate ./mongo.tfstate
+ - uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: tfstate
+ path: ./tf-test-automation/services/mongodb/mongo.tfstate
+ - name: Show mongo ip
+ run: |
+ echo ${{ steps.mongo_ip.outputs.mongo_ip }}
+
+ master_control:
+ runs-on: ubuntu-latest
+
+ needs: [xmeter_start, terraform_emqx, terraform_mysql, terraform_redis, terraform_pgsql, terraform_mongo]
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '8.0.282' # The JDK version to make available on the path.
+ java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk
+ architecture: x64 # (x64 or x86) - defaults to x64
+ - name: install jmeter
+ timeout-minutes: 10
+ env:
+ JMETER_VERSION: 5.3
+ run: |
+ wget --no-verbose --no-check-certificate -O /tmp/apache-jmeter.tgz https://downloads.apache.org/jmeter/binaries/apache-jmeter-$JMETER_VERSION.tgz
+ cd /tmp && tar -xvf apache-jmeter.tgz
+ echo "jmeter.save.saveservice.output_format=xml" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties
+ echo "jmeter.save.saveservice.response_data.on_error=true" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties
+ wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/ext/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar https://raw.githubusercontent.com/xmeter-net/mqtt-jmeter/master/Download/v2.0.2/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar
+ ln -s /tmp/apache-jmeter-$JMETER_VERSION /opt/jmeter
+ - name: install jmeter plugin
+ run: |
+ wget --no-verbose -O "/opt/jmeter/lib/mysql-connector-java-8.0.16.jar" https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar
+ - name: run jmeter
+ run: |
+ /opt/jmeter/bin/jmeter.sh \
+ -Jjmeter.save.saveservice.output_format=xml -n \
+ -t .ci/broker-performance-test-suite/broker_attestation_test.jmx \
+ -Demqx_ip=${{ needs.terraform_emqx.outputs.emqx_public_ip }} \
+ -Demqx_private_ip1=${{ needs.terraform_emqx.outputs.emqx_node_ip1 }} \
+ -Demqx_private_ip2=${{ needs.terraform_emqx.outputs.emqx_node_ip2 }} \
+ -Demqx_private_ip3=${{ needs.terraform_emqx.outputs.emqx_node_ip3 }} \
+ -Dmysql_ip=${{ needs.terraform_mysql.outputs.mysql_ip }} \
+ -Dpgsql_ip=${{ needs.terraform_pgsql.outputs.pgsql_ip }} \
+ -Dredis_ip=${{ needs.terraform_redis.outputs.redis_ip }} \
+ -Dmongo_ip=${{ needs.terraform_mongo.outputs.mongo_ip }} \
+ -Dxmeter_ip=${{ secrets.XMETER_IP }} \
+ -Dplugins_path="/opt/jmeter/lib/ext" \
+ -Dxmeter_user=${{ secrets.XMETER_USER }} \
+ -Dxmeter_pwd=${{ secrets.XMETER_PWD }} \
+ -Dscripts_path=".ci/performance-test-suite" \
+ -Dreport_file="jmeter_logs/report.txt" \
+ -l jmeter_logs/xmeter_process.jtl \
+ -j jmeter_logs/xmeter_process.log
+ - name: check logs
+ run: |
+ if cat jmeter_logs/xmeter_process.jtl | grep -e 'true' > /dev/null 2>&1; then
+ echo "check logs filed"
+ fi
+ - name: check report
+ run: |
+ if cat jmeter_logs/report.txt | grep -e 'err_report_id' > /dev/null 2>&1; then
+ echo "check report filed"
+ exit 1
+ fi
+ - uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: jmeter_logs_report
+ path: ./jmeter_logs
+
+ terraform_destroy:
+ runs-on: ubuntu-latest
+
+ needs: [master_control]
+ steps:
+ - name: Checkout tf-test-automation
+ uses: actions/checkout@v2
+ with:
+ repository: emqx/tf-test-automation
+ ref: cluster
+ path: tf-test-automation
+ - name: Setup Terraform
+ uses: hashicorp/setup-terraform@v1.3.2
+ with:
+ terraform_wrapper: false
+ - uses: actions/download-artifact@v2
+ with:
+ name: tfstate
+ path: ./tf-test-automation/services
+ - name: Terraform Init mysql
+ working-directory: ./tf-test-automation/services
+ run: |
+ cp mysql.tfstate ./mysql/terraform.tfstate
+ cd ./mysql
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Destroy mysql
+ working-directory: ./tf-test-automation/services/mysql
+ run: |
+ terraform destroy -auto-approve -var="db_password=public123" -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Init emqx
+ working-directory: ./tf-test-automation/services
+ run: |
+ cp emqx.tfstate ./emqx/terraform.tfstate
+ cd ./emqx
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Destroy emqx
+ working-directory: ./tf-test-automation/services/emqx
+ run: |
+ terraform destroy -auto-approve -var="region=ap-southeast-1" -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Init redis
+ working-directory: ./tf-test-automation/services
+ run: |
+ cp redis.tfstate ./redis/terraform.tfstate
+ cd ./redis
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Destroy redis
+ working-directory: ./tf-test-automation/services/redis
+ run: |
+ terraform destroy -auto-approve -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}" -var="private_key=${{ secrets.CI_SSH_PRIVATE_KEY }}"
+ - name: Terraform Init pgsql
+ working-directory: ./tf-test-automation/services
+ run: |
+ cp pgsql.tfstate ./pgsql/terraform.tfstate
+ cd ./pgsql
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Destroy pgsql
+ working-directory: ./tf-test-automation/services/pgsql
+ run: |
+ terraform destroy -auto-approve -var="db_password=public123" -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Init mongo
+ working-directory: ./tf-test-automation/services
+ run: |
+ cp mongo.tfstate ./mongodb/terraform.tfstate
+ cd ./mongodb
+ terraform init --backend-config="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" --backend-config="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+ - name: Terraform Destroy mongo
+ working-directory: ./tf-test-automation/services/mongodb
+ run: |
+ terraform destroy -auto-approve -var="db_password=public123" -var="access_key=${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}" -var="secret_key=${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}"
+
+ xmeter_stop:
+ runs-on: ubuntu-latest
+
+ needs: [terraform_destroy]
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v1
+ with:
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_FOR_PERFORMANCE_TESTING }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_FOR_PERFORMANCE_TESTING }}
+ aws-region: ap-southeast-1
+ - name: Start Xmeter Services
+ run: |
+ aws ec2 stop-instances --instance-ids i-0dd6d99916baaa1a8
+ aws ec2 stop-instances --instance-ids i-05222103df01eb2d7
+ aws ec2 stop-instances --instance-ids i-0c5dccd394ed9be18
+ aws ec2 stop-instances --instance-ids i-04c1c50b3e4952266
+
+
+