-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathbulk-patch.js
More file actions
115 lines (105 loc) · 3.52 KB
/
bulk-patch.js
File metadata and controls
115 lines (105 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
const axios = require("axios");
const parseLinkHeader = require("parse-link-header");
const ACCESS_TOKEN = "enter your access token here";
const searchConfig = {
headers: {
"User-Agent": "Mozilla/5.0",
Authorization: `Bearer ${ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
};
const patchConfig = {
headers: {
"User-Agent": "Mozilla/5.0",
Authorization: `Bearer ${ACCESS_TOKEN}`,
"Content-Type": "application/json-patch+json",
},
};
// Fill in any search limits you want to put on the selection of devices that you want to apply a setting to
const searchParams = [
["personId", null],
["placeId", null],
["orgId", null],
["displayName", null],
["product", null],
["tag", null],
["connectionStatus", null],
["serial", null],
["software", null],
["upgradeChannel", null],
["errorCode", null],
["capability", null],
["permission", null],
];
// Uncomment and replace example with setting(s) you want to bulk apply
const bulkSettings = [
// {
// op: 'replace',
// path: 'NetworkServices.HTTP.Mode/sources/configured/value',
// value: 'HTTP+HTTPS',
// },
// {
// op: 'remove',
// path: 'NetworkServices.HTTP.Mode/sources/configured/value',
// },
];
// Convert searchParamms into the params part of the url
const filteredParams = searchParams.filter(([key, value]) => value !== null);
const devicesQuery =
filteredParams.length === 0
? ""
: "?" + filteredParams.map(([key, value]) => `${key}=${value}`).join("&");
// Recursive function to fetch all devices across pages
const getDevices = (url, retries) => {
return axios.get(url, searchConfig).then((result) => {
console.log(`- Fetched ${url}`);
if (result.headers.link) {
const link = parseLinkHeader(result.headers.link);
return Promise.all([
result.data.items,
getDevices(link.next.url),
]).then((pages) => Array.prototype.concat.apply([], pages));
} else {
return result.data.items;
}
})
.catch(error => {
handleError(retries => getDevices(url, retries), `Fetching ${url}`, error, retries);
});
};
const patchDevice = (device, url, body, retries) => {
return axios
.patch(url, body, patchConfig)
.then(() => {
console.log(`- Patched ${url} (${device.displayName})`);
})
.catch((error) => {
handleError((retries) => patchDevice(device, url, body, retries), `Patching ${url} (${device.displayName})`, error, retries);
});
};
const handleError = (operation, operationText, error, retries) => {
if (error.response) {
if (retries > 0 && error.response.headers.hasOwnProperty('Retry-After')) {
console.log(`${error.response.status}: Retrying after ${error.response.headers['Retry-After']} ms`);
return new Promise(resolve =>
setTimeout(() => resolve(operation(retries - 1)), error.response.headers['Retry-After']));
}
console.log(
`- ${operationText} resulted in a ${error.response.status}: ${error.response.data.message}. trackingid: ${error.response.headers.trackingid}`
);
}
};
// Patch every device with settings from bulkSettings
console.log("\nGetting devices...");
getDevices(`https://webexapis.com/v1/devices${devicesQuery}`).then(
(devices) => {
console.log(
`\nApplying ${bulkSettings.length} settings to ${devices.length} devices...`
);
devices.forEach((device) => {
const url = `https://webexapis.com/v1/deviceConfigurations?deviceId=${device.id}`;
const body = JSON.stringify(bulkSettings);
patchDevice(device, url, body, 2);
});
}
);