Skip to content

Commit 2767963

Browse files
authored
Merge pull request #80 from VKCOM/sync/2025-01-20
Sync 2025-01-20
2 parents ae03d8c + 0128e8f commit 2767963

File tree

19 files changed

+477
-177
lines changed

19 files changed

+477
-177
lines changed

doc/API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Overview
44

5-
STF API is a RESTFull API which allows you to reserve and release any STF device. Internally STF uses [Swagger](http://swagger.io/) interface for its API implementation. For those who don't know about Swagger, Swagger provides specifications for RESTful apis. By using it you can generate documentation and client SDKs in various language automatically for Swagger-enabled apps. This gives you power to use STF APIs in any language of your favorite. You can read more about Swagger [here](http://swagger.io/getting-started/).
5+
STF API is a RESTFull API which allows you to reserve and release any STF device. Internally STF uses [Swagger](http://swagger.io/) interface for its API implementation. For those who don't know about Swagger, Swagger provides specifications for RESTful apis. By using it you can generate documentation and client SDKs in various language automatically for Swagger-enabled apps. This gives you power to use STF APIs in any language of your favorite. You can read more about Swagger [here](http://swagger.io/getting-started/).
66

77
## Swagger documentation
88

docker-compose-test.yaml

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,70 +7,70 @@ services:
77
container_name: mongo1
88
entrypoint:
99
["mongod", "--replSet", "myReplicaSet", "--bind_ip", "localhost,mongo1"]
10-
networks:
11-
default:
12-
ipv4_address: 10.211.0.2
13-
mongo2:
14-
image: mongo:6.0.10
15-
hostname: mongo2
16-
container_name: mongo2
17-
entrypoint:
18-
["mongod", "--replSet", "myReplicaSet", "--bind_ip", "localhost,mongo2"]
19-
networks:
20-
default:
21-
ipv4_address: 10.211.0.3
22-
mongo3:
23-
image: mongo:6.0.10
24-
hostname: mongo3
25-
container_name: mongo3
26-
entrypoint:
27-
["mongod", "--replSet", "myReplicaSet", "--bind_ip", "localhost,mongo3"]
28-
networks:
29-
default:
30-
ipv4_address: 10.211.0.4
3110
mongosetup:
3211
image: mongo:6.0.10
3312
depends_on:
3413
- mongo1
35-
- mongo2
36-
- mongo3
3714
volumes:
38-
- ./scripts/mongo_setup.sh:/scripts/mongo_setup.sh
15+
- ./scripts/mongo_setup_test.sh:/scripts/mongo_setup_test.sh
3916
restart: "no"
40-
entrypoint: ["bash", "/scripts/mongo_setup.sh"]
17+
entrypoint: ["bash", "/scripts/mongo_setup_test.sh"]
4118
adb:
4219
container_name: adb
4320
image: devicefarmer/adb:latest
4421
restart: unless-stopped
4522
volumes:
4623
- "/dev/bus/usb:/dev/bus/usb"
4724
privileged: true
48-
networks:
49-
default:
50-
ipv4_address: 10.211.0.6
5125
devicehub:
5226
container_name: devicehub
5327
build: .
54-
image: devicehub
28+
image: devicehub:latest
5529
ports:
5630
- "7100:7100"
5731
- "7110:7110"
5832
- "7400-7500:7400-7500"
5933
environment:
6034
- TZ='America/Los_Angeles'
61-
- MONGODB_PORT_27017_TCP=mongodb://10.211.0.2:27017
62-
- STF_ADMIN_EMAIL='test@example.com'
63-
- STF_ADMIN_NAME='test admin'
35+
- MONGODB_PORT_27017_TCP=mongodb://mongo1:27017
36+
- STF_ADMIN_EMAIL=administrator@fakedomain.com
37+
- STF_ADMIN_NAME=administrator
6438
restart: unless-stopped
6539
command: stf local --adb-host adb --public-ip 0.0.0.0 --provider-min-port 7400 --provider-max-port 7500
66-
networks:
67-
default:
68-
ipv4_address: 10.211.0.5
69-
networks:
70-
default:
71-
driver: bridge
72-
ipam:
73-
driver: default
74-
config:
75-
- subnet: 10.211.0.0/16
76-
gateway: 10.211.0.1
40+
healthcheck:
41+
test: [ "CMD", "curl", "-f", "http://devicehub:7100/auth/contact" ]
42+
interval: 20s
43+
timeout: 10s
44+
retries: 5
45+
depends_on:
46+
mongosetup:
47+
condition: service_completed_successfully
48+
adb:
49+
condition: service_started
50+
devicehub-generate-fake-device:
51+
image: devicehub:latest
52+
environment:
53+
- MONGODB_PORT_27017_TCP=mongodb://mongo1:27017
54+
container_name: devicehub-generate-fake-device
55+
command: stf generate-fake-device fake-device-type --number 5
56+
depends_on:
57+
devicehub:
58+
condition: service_healthy
59+
restart: "no"
60+
devicehub-pytest:
61+
build: test/api/
62+
environment:
63+
- PIP_DISABLE_PIP_VERSION_CHECK=1
64+
container_name: devicehub-pytest
65+
command:
66+
- /bin/sh
67+
- -c
68+
- |
69+
. /scripts/token.sh &&
70+
pytest ./ --token=$$STF_TOKEN --base-url=http://devicehub:7100 --log-cli-level=DEBUG
71+
volumes:
72+
- ./scripts/token.sh:/scripts/token.sh
73+
depends_on:
74+
devicehub-generate-fake-device:
75+
condition: service_completed_successfully
76+
restart: "no"

lib/cli/generate-fake-device/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ export const command = 'generate-fake-device <model>'
44
export const builder = function(yargs) {
55
return yargs
66
.strict()
7-
.option('n', {
8-
alias: 'number'
7+
.option('number', {
8+
alias: 'n'
99
, describe: 'How many devices to create.'
1010
, type: 'number'
1111
, default: 1

lib/db/api.js

Lines changed: 79 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,50 +2385,77 @@ export const saveDeviceIdentity = function(serial, identity) {
23852385
})
23862386
}
23872387

2388+
const findDevices = function(findCondition, neededField) {
2389+
return db.connect().then(client => {
2390+
var res = client.collection('devices').find(findCondition)
2391+
if (neededField) {
2392+
// 'field1,field2,field3' -> {field1:1, field2:1, field3:1}
2393+
let fieldsDict = neededField.split(',').reduce(function(result, field) {
2394+
if(field && field.trim().length > 0) {
2395+
return {
2396+
...result
2397+
, [field.trim()]: 1
2398+
}
2399+
}
2400+
else {
2401+
return {
2402+
...result,
2403+
}
2404+
}
2405+
}, {_id: 0})
2406+
res = res.project(fieldsDict)
2407+
}
2408+
return res.toArray()
2409+
})
2410+
}
2411+
2412+
const findDevice = function(findCondition, neededField) {
2413+
return db.connect().then(client => {
2414+
let res = client.collection('devices').findOne(findCondition)
2415+
if (neededField) {
2416+
// 'field1,field2,field3' -> {field1:1, field2:1, field3:1}
2417+
let fieldsDict = neededField.split(',').reduce(function(result, field) {
2418+
return {
2419+
...result
2420+
, [field.trim()]: 1,
2421+
}
2422+
}, {})
2423+
return res.project(fieldsDict)
2424+
}
2425+
return res
2426+
})
2427+
}
2428+
23882429
// dbapi.loadDevices = function(groups) {
2389-
export const loadDevices = function(groups) {
2430+
export const loadDevices = function(groups, fields) {
23902431
return trace('loadDevices', {groups}, () => {
2391-
return db.connect().then(client => {
2392-
if (groups.length > 0) {
2393-
return client.collection('devices').find(
2394-
{
2395-
'group.id': {$in: groups}
2396-
}
2397-
).toArray()
2398-
}
2399-
else {
2400-
return client.collection('devices').find().toArray()
2401-
}
2402-
})
2432+
if (groups && groups.length > 0) {
2433+
return findDevices({'group.id': {$in: groups}}, fields)
2434+
}
2435+
else {
2436+
return findDevices({}, fields)
2437+
}
24032438
})
24042439
}
24052440

24062441
// dbapi.loadDevicesByOrigin = function(groups) {
2407-
export const loadDevicesByOrigin = function(groups) {
2442+
export const loadDevicesByOrigin = function(groups, fields) {
24082443
return trace('loadDevicesByOrigin', {groups}, () => {
2409-
return db.connect().then(client => {
2410-
return client.collection('devices').find(
2411-
{'group.origin': {$in: groups}}
2412-
).toArray()
2413-
})
2444+
return findDevices({'group.origin': {$in: groups}}, fields)
24142445
})
24152446
}
24162447

24172448
// dbapi.loadBookableDevices = function(groups) {
2418-
export const loadBookableDevices = function(groups) {
2449+
export const loadBookableDevices = function(groups, fields) {
24192450
return trace('loadBookableDevices', {groups}, () => {
2420-
return db.connect().then(client => {
2421-
return client.collection('devices').find(
2422-
{
2423-
$and: [
2424-
{'group.origin': {$in: groups}}
2425-
, {present: {$eq: true}}
2426-
, {ready: {$eq: true}}
2427-
, {owner: {$eq: null}}
2428-
]
2429-
}
2430-
).toArray()
2431-
})
2451+
return findDevices({
2452+
$and: [
2453+
{'group.origin': {$in: groups}}
2454+
, {present: {$eq: true}}
2455+
, {ready: {$eq: true}}
2456+
, {owner: {$eq: null}}
2457+
]
2458+
}, fields)
24322459
})
24332460
}
24342461

@@ -2485,16 +2512,12 @@ export const loadBookableDevicesWithFiltersLock = function(groups, abi, model, t
24852512
}
24862513

24872514
// dbapi.loadStandardDevices = function(groups) {
2488-
export const loadStandardDevices = function(groups) {
2515+
export const loadStandardDevices = function(groups, fields) {
24892516
return trace('loadStandardDevices', {groups}, () => {
2490-
return db.connect().then(client => {
2491-
return client.collection('devices')
2492-
.find({
2493-
'group.class': apiutil.STANDARD
2494-
, 'group.id': {$in: groups}
2495-
})
2496-
.toArray()
2497-
})
2517+
return findDevices({
2518+
'group.class': apiutil.STANDARD
2519+
, 'group.id': {$in: groups}
2520+
}, fields)
24982521
})
24992522
}
25002523

@@ -2508,11 +2531,9 @@ export const loadPresentDevices = function() {
25082531
}
25092532

25102533
// dbapi.loadDeviceBySerial = function(serial) {
2511-
export const loadDeviceBySerial = function(serial) {
2534+
export const loadDeviceBySerial = function(serial, fields) {
25122535
return trace('loadDeviceBySerial', {serial}, () => {
2513-
return db.connect().then(client => {
2514-
return client.collection('devices').findOne({serial: serial})
2515-
})
2536+
return findDevice({serial: serial}, fields)
25162537
})
25172538
}
25182539

@@ -2526,16 +2547,12 @@ export const loadDevicesBySerials = function(serials) {
25262547
}
25272548

25282549
// dbapi.loadDevice = function(groups, serial) {
2529-
export const loadDevice = function(groups, serial) {
2550+
export const loadDevice = function(groups, serial, fields) {
25302551
return trace('loadDevice', {groups, serial}, () => {
2531-
return db.connect().then(client => {
2532-
return client.collection('devices').findOne(
2533-
{
2534-
serial: serial
2535-
, 'group.id': {$in: groups}
2536-
}
2537-
)
2538-
})
2552+
return findDevice({
2553+
serial: serial
2554+
, 'group.id': {$in: groups}
2555+
}, fields)
25392556
})
25402557
}
25412558

@@ -2592,14 +2609,21 @@ export const loadDeviceByOrigin = function(groups, serial) {
25922609
export const saveUserAccessToken = function(email, token) {
25932610
return trace('saveUserAccessToken', {email, token}, () => {
25942611
return db.connect().then(client => {
2612+
let tokenId = token.id
25952613
return client.collection('accessTokens').insertOne(
25962614
{
25972615
email: email
25982616
, id: token.id
25992617
, title: token.title
26002618
, jwt: token.jwt
2619+
}).then(function(result) {
2620+
if (result.insertedId) {
2621+
return tokenId
26012622
}
2602-
)
2623+
else {
2624+
throw Error('AccessToken have not saved at database. Check MongoDB logs')
2625+
}
2626+
})
26032627
})
26042628
})
26052629
}

lib/units/api/controllers/autotests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ function freeDevices(req, res) {
9797
, query: {
9898
redirected: true
9999
}
100+
, options: req.options
100101
}
101102
groups.deleteGroups(request, res)
102103
}

lib/units/api/controllers/devices.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function filterGenericDevices(req, res, devices) {
3333
}
3434
function getGenericDevices(req, res, loadDevices) {
3535
log.info(req.user)
36-
loadDevices(req.user.groups.subscribed).then(function(devices) {
36+
loadDevices(req.user.groups.subscribed, req.query.fields).then(function(devices) {
3737
let isGenerator = false // req.headers.is_generator === '1'
3838
if (isGenerator) {
3939
let count = 0
@@ -114,7 +114,7 @@ function extractStandardizableDevices(devices) {
114114
})
115115
}
116116
function getStandardizableDevices(req, res) {
117-
dbapi.loadDevicesByOrigin(req.user.groups.subscribed).then(function(devices) {
117+
dbapi.loadDevicesByOrigin(req.user.groups.subscribed, req.query.fields).then(function(devices) {
118118
extractStandardizableDevices(devices).then(function(devices) {
119119
filterGenericDevices(req, res, devices)
120120
})
@@ -251,6 +251,7 @@ function getDeviceBySerial(req, res) {
251251
}
252252
res.json({
253253
success: true
254+
, description: 'Device Information'
254255
, device: responseDevice
255256
})
256257
})
@@ -322,7 +323,7 @@ function getDeviceType(req, res) {
322323
function getDeviceBookings(req, res) {
323324
const serial = req.params.serial
324325
const fields = req.query.fields
325-
dbapi.loadDevice(req.user.groups.subscribed, serial).then(function(groups) {
326+
dbapi.loadDevice(req.user.groups.subscribed, serial, fields).then(function(groups) {
326327
return groups
327328
})
328329
.then(function(devices) {
@@ -436,7 +437,7 @@ function addOriginGroupDevices(req, res) {
436437
return group.devices.indexOf(serial) < 0
437438
}))
438439
}
439-
return dbapi.loadDevicesByOrigin(req.user.groups.subscribed).then(function(devices) {
440+
return dbapi.loadDevicesByOrigin(req.user.groups.subscribed, req.query.fields).then(function(devices) {
440441
if (group.class === apiutil.BOOKABLE) {
441442
return devices
442443
}
@@ -556,7 +557,7 @@ function deleteDevices(req, res) {
556557
}
557558
(function() {
558559
if (typeof serials === 'undefined') {
559-
return dbapi.loadDevicesByOrigin(req.user.groups.subscribed).then(function(devices) {
560+
return dbapi.loadDevicesByOrigin(req.user.groups.subscribed, req.query.fields).then(function(devices) {
560561
return removeDevices(devices.map(function(device) {
561562
return device.serial
562563
}))

0 commit comments

Comments
 (0)