aws-iot-device-sdk-v2
Version:
NodeJS API for the AWS IoT service
336 lines • 15.6 kB
JavaScript
;
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const aws_crt_1 = require("aws-crt");
const uuid_1 = require("uuid");
const events_1 = require("events");
const iotjobsclientv2_1 = require("./iotjobsclientv2");
const client_iot_1 = require("@aws-sdk/client-iot");
const model = __importStar(require("./model"));
jest.setTimeout(30000);
function hasTestEnvironment() {
if (process.env.AWS_TEST_MQTT5_IOT_CORE_HOST === undefined) {
return false;
}
if (process.env.AWS_TEST_MQTT5_IOT_CERTIFICATE_PATH === undefined) {
return false;
}
if (process.env.AWS_TEST_MQTT5_IOT_KEY_PATH === undefined) {
return false;
}
if (process.env.AWS_TEST_MQTT5_IOT_CORE_REGION === undefined) {
return false;
}
return true;
}
const conditional_test = (condition) => condition ? it : it.skip;
function build_protocol_client_mqtt5() {
let builder = aws_crt_1.iot.AwsIotMqtt5ClientConfigBuilder.newDirectMqttBuilderWithMtlsFromPath(
// @ts-ignore
process.env.AWS_TEST_MQTT5_IOT_CORE_HOST, process.env.AWS_TEST_MQTT5_IOT_CERTIFICATE_PATH, process.env.AWS_TEST_MQTT5_IOT_KEY_PATH);
builder.withConnectProperties({
clientId: `test-${(0, uuid_1.v4)()}`,
keepAliveIntervalSeconds: 1200,
});
return new aws_crt_1.mqtt5.Mqtt5Client(builder.build());
}
function build_protocol_client_mqtt311() {
// @ts-ignore
let builder = aws_crt_1.iot.AwsIotMqttConnectionConfigBuilder.new_mtls_builder_from_path(process.env.AWS_TEST_MQTT5_IOT_CERTIFICATE_PATH, process.env.AWS_TEST_MQTT5_IOT_KEY_PATH);
// @ts-ignore
builder.with_endpoint(process.env.AWS_TEST_MQTT5_IOT_CORE_HOST);
builder.with_client_id(`test-${(0, uuid_1.v4)()}`);
let client = new aws_crt_1.mqtt.MqttClient();
return client.new_connection(builder.build());
}
var ProtocolVersion;
(function (ProtocolVersion) {
ProtocolVersion[ProtocolVersion["Mqtt311"] = 0] = "Mqtt311";
ProtocolVersion[ProtocolVersion["Mqtt5"] = 1] = "Mqtt5";
})(ProtocolVersion || (ProtocolVersion = {}));
class JobsTestingContext {
startProtocolClient() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.protocolStarted) {
this.protocolStarted = true;
if (this.mqtt5Client) {
let connected = (0, events_1.once)(this.mqtt5Client, aws_crt_1.mqtt5.Mqtt5Client.CONNECTION_SUCCESS);
this.mqtt5Client.start();
yield connected;
}
if (this.mqtt311Client) {
yield this.mqtt311Client.connect();
}
}
});
}
stopProtocolClient() {
return __awaiter(this, void 0, void 0, function* () {
if (this.protocolStarted) {
this.protocolStarted = false;
if (this.mqtt5Client) {
let stopped = (0, events_1.once)(this.mqtt5Client, aws_crt_1.mqtt5.Mqtt5Client.STOPPED);
this.mqtt5Client.stop();
yield stopped;
this.mqtt5Client.close();
}
if (this.mqtt311Client) {
yield this.mqtt311Client.disconnect();
}
}
});
}
constructor(options) {
var _a, _b;
this.protocolStarted = false;
if (options.version == ProtocolVersion.Mqtt5) {
this.mqtt5Client = build_protocol_client_mqtt5();
let rrOptions = {
maxRequestResponseSubscriptions: 6,
maxStreamingSubscriptions: 2,
operationTimeoutInSeconds: (_a = options.timeoutSeconds) !== null && _a !== void 0 ? _a : 60,
};
this.client = iotjobsclientv2_1.IotJobsClientv2.newFromMqtt5(this.mqtt5Client, rrOptions);
}
else {
this.mqtt311Client = build_protocol_client_mqtt311();
let rrOptions = {
maxRequestResponseSubscriptions: 6,
maxStreamingSubscriptions: 2,
operationTimeoutInSeconds: (_b = options.timeoutSeconds) !== null && _b !== void 0 ? _b : 60,
};
this.client = iotjobsclientv2_1.IotJobsClientv2.newFromMqtt311(this.mqtt311Client, rrOptions);
}
}
open() {
return __awaiter(this, void 0, void 0, function* () {
yield this.startProtocolClient();
});
}
close() {
return __awaiter(this, void 0, void 0, function* () {
this.client.close();
yield this.stopProtocolClient();
});
}
}
function doCreateDestroyTest(version) {
return __awaiter(this, void 0, void 0, function* () {
let context = new JobsTestingContext({
version: version
});
yield context.open();
yield context.close();
});
}
conditional_test(hasTestEnvironment())('jobsv2 - create destroy mqtt5', () => __awaiter(void 0, void 0, void 0, function* () {
yield doCreateDestroyTest(ProtocolVersion.Mqtt5);
}));
conditional_test(hasTestEnvironment())('jobsv2 - create destroy mqtt311', () => __awaiter(void 0, void 0, void 0, function* () {
yield doCreateDestroyTest(ProtocolVersion.Mqtt311);
}));
//@ts-ignore
let jobResources = {};
function createJob(client, index) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
let jobId = 'jobid-' + (0, uuid_1.v4)();
let jobDocument = {
test: `do-something${index}`
};
const createJobCommand = new client_iot_1.CreateJobCommand({
jobId: jobId,
targets: [(_a = jobResources.thingGroupArn) !== null && _a !== void 0 ? _a : ""],
document: JSON.stringify(jobDocument),
targetSelection: "CONTINUOUS"
});
yield client.send(createJobCommand);
return jobId;
});
}
function deleteJob(client, jobId) {
return __awaiter(this, void 0, void 0, function* () {
if (jobId) {
const command = new client_iot_1.DeleteJobCommand({
jobId: jobId,
force: true
});
yield client.send(command);
}
});
}
beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
jobResources = {};
const client = new client_iot_1.IoTClient({
region: process.env.AWS_TEST_MQTT5_IOT_CORE_REGION,
});
let thingGroupName = 'tgn-' + (0, uuid_1.v4)();
const createThingGroupCommand = new client_iot_1.CreateThingGroupCommand({
thingGroupName: thingGroupName
});
const createThingGroupResponse = yield client.send(createThingGroupCommand);
jobResources.thingGroupName = thingGroupName;
jobResources.thingGroupArn = createThingGroupResponse.thingGroupArn;
let thingName = 't-' + (0, uuid_1.v4)();
const createThingCommand = new client_iot_1.CreateThingCommand({
thingName: thingName
});
yield client.send(createThingCommand);
jobResources.thingName = thingName;
yield new Promise(r => setTimeout(r, 1000));
jobResources.jobId1 = yield createJob(client, 1);
yield new Promise(r => setTimeout(r, 1000));
}));
afterEach(() => __awaiter(void 0, void 0, void 0, function* () {
const client = new client_iot_1.IoTClient({
region: process.env.AWS_TEST_MQTT5_IOT_CORE_REGION,
});
yield new Promise(r => setTimeout(r, 1000));
yield deleteJob(client, jobResources.jobId1);
yield new Promise(r => setTimeout(r, 1000));
if (jobResources.thingName) {
const command = new client_iot_1.DeleteThingCommand({
thingName: jobResources.thingName
});
yield client.send(command);
yield new Promise(r => setTimeout(r, 1000));
}
if (jobResources.thingGroupName) {
const command = new client_iot_1.DeleteThingGroupCommand({
thingGroupName: jobResources.thingGroupName
});
yield client.send(command);
}
jobResources = {};
}));
function verifyNoJobExecutions(context) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
let response = yield context.client.getPendingJobExecutions({
thingName: (_a = jobResources.thingName) !== null && _a !== void 0 ? _a : ""
});
// @ts-ignore
expect(response.inProgressJobs.length).toEqual(0);
// @ts-ignore
expect(response.queuedJobs.length).toEqual(0);
});
}
function attachThingToThingGroup(client) {
return __awaiter(this, void 0, void 0, function* () {
const addThingToThingGroupCommand = new client_iot_1.AddThingToThingGroupCommand({
thingName: jobResources.thingName,
thingGroupName: jobResources.thingGroupName
});
yield client.send(addThingToThingGroupCommand);
});
}
function doProcessingTest(version) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
return __awaiter(this, void 0, void 0, function* () {
const client = new client_iot_1.IoTClient({});
let context = new JobsTestingContext({
version: version
});
yield context.open();
// set up streaming operations for our test's thing
let jobExecutionChangedStream = context.client.createJobExecutionsChangedStream({
thingName: (_a = jobResources.thingName) !== null && _a !== void 0 ? _a : ""
});
jobExecutionChangedStream.open();
let nextJobExecutionChangedStream = context.client.createNextJobExecutionChangedStream({
thingName: (_b = jobResources.thingName) !== null && _b !== void 0 ? _b : ""
});
nextJobExecutionChangedStream.open();
let initialExecutionChangedWaiter = (0, events_1.once)(jobExecutionChangedStream, 'incomingPublish');
let initialNextJobExecutionChangedWaiter = (0, events_1.once)(nextJobExecutionChangedStream, 'incomingPublish');
// thing is brand new, nothing should be pending
yield verifyNoJobExecutions(context);
// as soon as we attach the thing to the thing group which has a continuous job associated with it, a
// job execution should become queued for our thing
yield attachThingToThingGroup(client);
let initialJobExecutionChanged = (yield initialExecutionChangedWaiter)[0].message;
// @ts-ignore
expect(initialJobExecutionChanged.jobs['QUEUED'].length).toEqual(1);
// @ts-ignore
expect(initialJobExecutionChanged.jobs['QUEUED'][0].jobId).toEqual(jobResources.jobId1);
let initialNextJobExecutionChanged = (yield initialNextJobExecutionChangedWaiter)[0].message;
expect((_c = initialNextJobExecutionChanged.execution) === null || _c === void 0 ? void 0 : _c.jobId).toEqual(jobResources.jobId1);
expect((_d = initialNextJobExecutionChanged.execution) === null || _d === void 0 ? void 0 : _d.status).toEqual(model.JobStatus.QUEUED);
let finalExecutionChangedWaiter = (0, events_1.once)(jobExecutionChangedStream, 'incomingPublish');
let finalNextJobExecutionChangedWaiter = (0, events_1.once)(nextJobExecutionChangedStream, 'incomingPublish');
// tell the service we'll run the next job
let startNextResponse = yield context.client.startNextPendingJobExecution({
thingName: (_e = jobResources.thingName) !== null && _e !== void 0 ? _e : ""
});
expect((_f = startNextResponse.execution) === null || _f === void 0 ? void 0 : _f.jobId).toEqual(jobResources.jobId1);
// pretend to do the job
yield new Promise(r => setTimeout(r, 1000));
// job execution should be in progress
let describeResponse = yield context.client.describeJobExecution({
thingName: (_g = jobResources.thingName) !== null && _g !== void 0 ? _g : "",
jobId: (_h = jobResources.jobId1) !== null && _h !== void 0 ? _h : "",
});
expect((_j = describeResponse.execution) === null || _j === void 0 ? void 0 : _j.jobId).toEqual(jobResources.jobId1);
expect((_k = describeResponse.execution) === null || _k === void 0 ? void 0 : _k.status).toEqual(model.JobStatus.IN_PROGRESS);
// tell the service we completed the job successfully
yield context.client.updateJobExecution({
thingName: (_l = jobResources.thingName) !== null && _l !== void 0 ? _l : "",
jobId: (_m = jobResources.jobId1) !== null && _m !== void 0 ? _m : "",
status: model.JobStatus.SUCCEEDED
});
yield new Promise(r => setTimeout(r, 3000));
let finalJobExecutionChanged = (yield finalExecutionChangedWaiter)[0].message;
expect(finalJobExecutionChanged.jobs).toEqual({});
let finalNextJobExecutionChanged = (yield finalNextJobExecutionChangedWaiter)[0].message;
expect(finalNextJobExecutionChanged.timestamp).toBeDefined();
let getPendingResponse = yield context.client.getPendingJobExecutions({
thingName: (_o = jobResources.thingName) !== null && _o !== void 0 ? _o : ""
});
expect((_p = getPendingResponse.queuedJobs) === null || _p === void 0 ? void 0 : _p.length).toEqual(0);
expect((_q = getPendingResponse.inProgressJobs) === null || _q === void 0 ? void 0 : _q.length).toEqual(0);
context.client.close();
yield context.close();
});
}
conditional_test(hasTestEnvironment())('jobsv2 processing mqtt5', () => __awaiter(void 0, void 0, void 0, function* () {
yield doProcessingTest(ProtocolVersion.Mqtt5);
}));
conditional_test(hasTestEnvironment())('jobsv2 processing mqtt311', () => __awaiter(void 0, void 0, void 0, function* () {
yield doProcessingTest(ProtocolVersion.Mqtt311);
}));
//# sourceMappingURL=iotjobsclientv2.spec.js.map