Skip to content

Commit 1ed6b15

Browse files
Communication phonenumbers siprouting (Azure#22248)
### Packages impacted by this PR communication\communication-phone-numbers ### Issues associated with this PR [User Story](https://skype.visualstudio.com/SPOOL/_workitems/edit/2532740) ### Describe the problem that is addressed by this PR The PR adds the sipRoutingClient into the communication-phone-numbers SDK. The client enables the management of SIP routing configuration for direct routing numbers. API supports GET and PATCH requests. Each Azure Communication resource has exactly one SIP configuration. The configuration contains of a dictionary of trunks and a list of routes. The trunks allow for partial updates, the configuration is merged with the incoming trunk dictionary. The routes don’t allow for partial updates, the whole list is replaced by the incoming list (if it is present on PATCH request). The sipRoutingClient provides more straightforward methods to retrieve and manage SIP trunks and routes. [Swagger](https://raw.githubusercontent.com/Azure/azure-rest-api-specs/15d66311cc2b64f04692fdf021d1b235b538e1bc/specification/communication/data-plane/SipRouting/preview/2021-05-01-preview/communicationservicessiprouting.json) [Examples](https://github.com/jannovak-msft/azure-sdk-for-js/tree/communication-phonenumbers-siprouting/sdk/communication/communication-phone-numbers/samples/v1/typescript/src/siprouting) ![image](https://user-images.githubusercontent.com/81623717/187804144-da7ef4f7-30e5-47af-8ea8-2848284f30a2.png) ### What are the possible designs available to address the problem? If there are more than one possible design, why was the one in this PR chosen? ### Are there test cases added in this PR? _(If not, why?)_ ### Provide a list of related PRs _(if any)_ ### Command used to generate this PR:**_(Applicable only to SDK release request PRs)_ ### Checklists - [x] Added impacted package name to the issue description - [ ] Does this PR needs any fixes in the SDK Generator?** _(If so, create an Issue in the [Autorest/typescript](https://github.com/Azure/autorest.typescript) repository and link it here)_ - [ ] Added a changelog (if necessary)
1 parent 6a3d6c0 commit 1ed6b15

File tree

212 files changed

+30122
-5162
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

212 files changed

+30122
-5162
lines changed

sdk/communication/communication-phone-numbers/README.md

Lines changed: 179 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,39 @@ To use this client library in the browser, first you need to use a bundler. For
2525

2626
## Key concepts
2727

28-
The phone numbers package exposes the `PhoneNumbersClient` which provides methods to manage phone numbers.
28+
This SDK provides functionality to easily manage `direct offer` and `direct routing` numbers.
2929

30-
### Phone number types
30+
The `direct offer` numbers come in two types: Geographic and Toll-Free. Geographic phone plans are phone plans associated with a location, whose phone numbers' area codes are associated with the area code of a geographic location. Toll-Free phone plans are phone plans not associated location. For example, in the US, toll-free numbers can come with area codes such as 800 or 888.
31+
They are managed using the `PhoneNumbersClient`
32+
33+
The `direct routing` feature enables connecting your existing telephony infrastructure to ACS.
34+
The configuration is managed using the `SipRoutingClient`, which provides methods for setting up SIP trunks and voice routing rules, in order to properly handle calls for your telephony subnet.
35+
36+
### Phone numbers client
37+
38+
#### Phone number types
3139

3240
Phone numbers come in two types; Geographic and Toll-Free. Geographic phone numbers are phone numbers associated with a location, whose area codes are associated with the area code of a geographic location. Toll-Free phone numbers are not associated with a location. For example, in the US, toll-free numbers can come with area codes such as 800 or 888.
3341

3442
All geographic phone numbers within the same country are grouped into a phone plan group with a Geographic phone number type. All Toll-Free phone numbers within the same country are grouped into a phone plan group.
3543

36-
### Searching and acquiring numbers
44+
#### Searching and acquiring numbers
3745

3846
Phone numbers can be searched through the search creation API by providing a phone number type (geographic or toll-free), assignment type (person or application), calling and sms capabilities, an area code and quantity of phone numbers. The provided quantity of phone numbers will be reserved for 15 minutes. This search of phone numbers can either be cancelled or purchased. If the search is cancelled, then the phone numbers will become available to others. If the search is purchased, then the phone numbers are acquired for the Azure resource.
3947

40-
### Configuring phone numbers
48+
#### Configuring phone numbers
4149

4250
Phone numbers can have a combination of capabilities. They can be configured to support inbound and/or outbound calling, or neither if you won't use the phone number for calling. The same applies to sms capabilities.
4351

4452
It is important to consider the assignment type of your phone number. Some capabilities are restricted to a particular assignment type.
4553

54+
### SIP routing client
55+
56+
Direct routing feature allows connecting customer-provided telephony infrastructure to Azure Communication Resources. In order to setup routing configuration properly, customer needs to supply the SIP trunk configuration and SIP routing rules for calls. SIP routing client provides the necessary interface for setting this configuration.
57+
58+
When the call arrives, system tries to match the destination number with regex number patterns of defined routes. The first route to match the number will be selected. The order of regex matching is the same as the order of routes in configuration, therefore the order of routes matters.
59+
Once a route is matched, the call is routed to the first trunk in the route's trunks list. If the trunk is not available, next trunk in the list is selected.
60+
4661
## Examples
4762

4863
## Authentication
@@ -51,7 +66,7 @@ To create a client object to access the Communication Services API, you will nee
5166

5267
You can get a key and/or connection string from your Communication Services resource in the [Azure Portal][azure_portal]. You can also find the endpoint for your Communication Services resource in the [Azure Portal][azure_portal].
5368

54-
Once you have a key, you can authenticate the `PhoneNumbersClient` with any of the following methods:
69+
Once you have a key, you can authenticate the client with any of the following methods:
5570

5671
### Using a connection string
5772

@@ -62,6 +77,13 @@ const connectionString = "endpoint=<endpoint>;accessKey=<accessKey>";
6277
const client = new PhoneNumbersClient(connectionString);
6378
```
6479

80+
```typescript
81+
import { SipRoutingClient } from "@azure/communication-phone-numbers";
82+
83+
const connectionString = "endpoint=<endpoint>;accessKey=<accessKey>";
84+
const client = new SipRoutingClient(connectionString);
85+
```
86+
6587
### Using an access key with `AzureKeyCredential`
6688

6789
If you use a key to initialize the client you will also need to provide the appropriate endpoint. You can get this endpoint from your Communication Services resource in [Azure Portal][azure_portal]. Once you have a key and endpoint, you can authenticate with the following code:
@@ -74,6 +96,14 @@ const credential = new AzureKeyCredential("<key-from-resource>");
7496
const client = new PhoneNumbersClient("<endpoint-from-resource>", credential);
7597
```
7698

99+
```typescript
100+
import { AzureKeyCredential } from "@azure/core-auth";
101+
import { SipRoutingClient } from "@azure/communication-phone-numbers";
102+
103+
const credential = new AzureKeyCredential("<key-from-resource>");
104+
const client = new SipRoutingClient("<endpoint-from-resource>", credential);
105+
```
106+
77107
### Using an Azure Active Directory Credential
78108

79109
Connection string authentication is used in most of the examples, but you can also authenticate with Azure Active Directory using the [Azure Identity library][azure_identity]. To use the [DefaultAzureCredential][defaultazurecredential] provider shown below, or other credential providers provided with the Azure SDK, please install the [`@azure/identity`][azure_identity] package:
@@ -92,18 +122,36 @@ let credential = new DefaultAzureCredential();
92122
const client = new PhoneNumbersClient("<endpoint-from-resource>", credential);
93123
```
94124

125+
```typescript
126+
import { DefaultAzureCredential } from "@azure/identity";
127+
import { SipRoutingClient } from "@azure/communication-phone-numbers";
128+
129+
let credential = new DefaultAzureCredential();
130+
const client = new SipRoutingClient("<endpoint-from-resource>", credential);
131+
```
132+
95133
## Usage
96134

97135
The following sections provide code snippets that cover some of the common tasks using the Azure Communication Services Phone Numbers client. The scenarios that are covered here consist of:
98136

137+
PhoneNumbersClient
99138
- [Search for available phone numbers](#search-for-available-phone-numbers)
100139
- [Purchase phone numbers from a search](#purchase-phone-numbers-from-a-search)
101140
- [Release a purchased phone number](#release-a-purchased-phone-number)
102141
- [Update phone number capabilities](#update-phone-number-capabilities)
103142
- [Get a purchased phone number](#get-a-purchased-phone-number)
104143
- [List purchased phone numbers](#list-purchased-phone-numbers)
105144

106-
### Search for available phone numbers
145+
SipRoutingClient
146+
- [Retrieve SIP trunks and routes](#retrieve-sip-trunks-and-routes)
147+
- [Replace SIP trunks and routes](#replace-sip-trunks-and-routes)
148+
- [Retrieve single trunk](#retrieve-single-trunk)
149+
- [Set single trunk](#set-single-trunk)
150+
- [Delete single trunk](#delete-single-trunk)
151+
152+
### PhoneNumbersClient
153+
154+
#### Search for available phone numbers
107155

108156
Use the `beginSearchAvailablePhoneNumbers` method to search for phone numbers and reserve them. The phone numbers returned are reserved for 15 minutes and can be purchased during this period by providing the `searchId` to the `beginPurchasePhoneNumbers` method.
109157

@@ -141,7 +189,7 @@ async function main() {
141189
main();
142190
```
143191

144-
### Purchase phone numbers from a search
192+
#### Purchase phone numbers from a search
145193

146194
Use the `beginPurchasePhoneNumbers` method to purchase the phone numbers from your search. Purchased phone numbers will be assigned to the Communication Services resource used when initiating the client. The `searchId` returned from `beginSearchAvailablePhoneNumbers` is required.
147195

@@ -180,7 +228,7 @@ async function main() {
180228
main();
181229
```
182230

183-
### Release a purchased phone number
231+
#### Release a purchased phone number
184232

185233
Use the `beginReleasePhoneNumber` method to release a previously purchased phone number. Released phone numbers will no longer be associated with the Communication Services resource, and will not be available for use with other operations (eg. SMS) of the resource. The phone number being released is required.
186234

@@ -205,7 +253,7 @@ async function main() {
205253
main();
206254
```
207255

208-
### Update phone number capabilities
256+
#### Update phone number capabilities
209257

210258
Use the `beginUpdatePhoneNumberCapabilities` method to update the capabilities of a purchased phone number. Phone numbers can be configured to support inbound and/or outbound calling and sms, or neither.
211259

@@ -242,7 +290,7 @@ async function main() {
242290
main();
243291
```
244292

245-
### Get a purchased phone number
293+
#### Get a purchased phone number
246294

247295
Use the `getPurchasedPhoneNumber` method to get information about a purchased phone number. This information includes the phone number's type, capabilities, cost, and purchase date.
248296

@@ -264,7 +312,7 @@ async main function() {
264312
main();
265313
```
266314

267-
### List purchased phone numbers
315+
#### List purchased phone numbers
268316

269317
Use the `listPurchasedPhoneNumbers` method to page through all purchased phone numbers.
270318

@@ -286,6 +334,126 @@ async main function() {
286334
main();
287335
```
288336

337+
### SipRoutingClient
338+
339+
#### Retrieve SIP trunks and routes
340+
341+
Get the list of currently configured trunks or routes.
342+
343+
```typescript
344+
import { SipRoutingClient } from "@azure/communication-phone-numbers";
345+
346+
const connectionString = "endpoint=<endpoint>;accessKey=<accessKey>";
347+
const client = new SipRoutingClient(connectionString);
348+
349+
async function main() {
350+
const trunks = await client.getTrunks();
351+
const routes = await client.getRoutes();
352+
for (const trunk of trunks) {
353+
console.log(`Trunk ${trunk.fqdn}:${trunk.sipSignalingPort}`);
354+
}
355+
356+
for (const route of routes) {
357+
console.log(`Route ${route.name} with pattern ${route.numberPattern}`);
358+
console.log(`Route's trunks: ${route.trunks?.join()}`);
359+
}
360+
}
361+
362+
main();
363+
```
364+
365+
#### Replace SIP trunks and routes
366+
367+
Replace the list of currently configured trunks or routes with new values.
368+
369+
```typescript
370+
import { SipRoutingClient } from "@azure/communication-phone-numbers";
371+
372+
const connectionString = "endpoint=<endpoint>;accessKey=<accessKey>";
373+
const client = new SipRoutingClient(connectionString);
374+
375+
async function main() {
376+
await client.setTrunks([
377+
{
378+
fqdn: 'sbc.one.domain.com',
379+
sipSignalingPort: 1234
380+
},{
381+
fqdn: 'sbc.two.domain.com',
382+
sipSignalingPort: 1234
383+
}
384+
]);
385+
386+
await client.setRoutes([
387+
{
388+
name: "First Route",
389+
description: "route's description",
390+
numberPattern: "^\+[1-9][0-9]{3,23}$",
391+
trunks: [ 'sbc.one.domain.com' ]
392+
},{
393+
name: "Second Route",
394+
description: "route's description",
395+
numberPattern: "^.*$",
396+
trunks: [ 'sbc.two.domain.com', 'sbc.one.domain.com' ]
397+
}
398+
]);
399+
}
400+
401+
main();
402+
```
403+
404+
#### Retrieve single trunk
405+
406+
```typescript
407+
import { SipRoutingClient } from "@azure/communication-phone-numbers";
408+
409+
const connectionString = "endpoint=<endpoint>;accessKey=<accessKey>";
410+
const client = new SipRoutingClient(connectionString);
411+
412+
async function main() {
413+
const trunk = await client.getTrunk('sbc.one.domain.com');
414+
if (trunk) {
415+
console.log(`Trunk ${trunk.fqdn}:${trunk.sipSignalingPort}`);
416+
} else {
417+
console.log('Trunk not found')
418+
}
419+
}
420+
421+
main();
422+
```
423+
424+
#### Set single trunk
425+
426+
```typescript
427+
import { SipRoutingClient } from "@azure/communication-phone-numbers";
428+
429+
const connectionString = "endpoint=<endpoint>;accessKey=<accessKey>";
430+
const client = new SipRoutingClient(connectionString);
431+
432+
async function main() {
433+
await client.setTrunk({
434+
fqdn: 'sbc.one.domain.com',
435+
sipSignalingPort: 4321
436+
});
437+
}
438+
439+
main();
440+
```
441+
442+
#### Delete single trunk
443+
444+
```typescript
445+
import { SipRoutingClient } from "@azure/communication-phone-numbers";
446+
447+
const connectionString = "endpoint=<endpoint>;accessKey=<accessKey>";
448+
const client = new SipRoutingClient(connectionString);
449+
450+
async function main() {
451+
await client.deleteTrunk('sbc.one.domain.com');
452+
}
453+
454+
main();
455+
```
456+
289457
## Troubleshooting
290458

291459
## Next steps

sdk/communication/communication-phone-numbers/karma.conf.js

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
// https://github.com/karma-runner/karma-chrome-launcher
22
process.env.CHROME_BIN = require("puppeteer").executablePath();
33
require("dotenv").config();
4-
const {
5-
jsonRecordingFilterFunction,
6-
isPlaybackMode,
7-
isSoftRecordMode,
8-
isRecordMode,
9-
} = require("@azure-tools/test-recorder");
4+
const { relativeRecordingsPath } = require("@azure-tools/test-recorder");
5+
6+
process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath();
107

118
// Get all variables containing the available phone numbers per test agent.
129
// E.g. -> AZURE_PHONE_NUMBER_windows_2019_node12
@@ -34,14 +31,10 @@ module.exports = function (config) {
3431
"karma-coverage",
3532
"karma-sourcemap-loader",
3633
"karma-junit-reporter",
37-
"karma-json-to-file-reporter",
38-
"karma-json-preprocessor",
3934
],
4035

4136
// list of files / patterns to load in the browser
42-
files: ["dist-test/index.browser.js"].concat(
43-
isPlaybackMode() || isSoftRecordMode() ? ["recordings/browsers/**/*.json"] : []
44-
),
37+
files: ["dist-test/index.browser.js"],
4538

4639
// list of files / patterns to exclude
4740
exclude: [],
@@ -50,7 +43,6 @@ module.exports = function (config) {
5043
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
5144
preprocessors: {
5245
"**/*.js": ["sourcemap", "env"],
53-
"recordings/browsers/**/*.json": ["json"],
5446
// IMPORTANT: COMMENT following line if you want to debug in your browsers!!
5547
// Preprocess source file to calculate code coverage, however this will make source file unreadable
5648
//"dist-test/index.browser.js": ["coverage"]
@@ -72,13 +64,14 @@ module.exports = function (config) {
7264
"SKIP_UPDATE_CAPABILITIES_LIVE_TESTS",
7365
"AZURE_TEST_AGENT",
7466
"AZURE_USERAGENT_OVERRIDE",
67+
"RECORDINGS_RELATIVE_PATH",
7568
...getPhoneNumberPoolEnvVars(),
7669
],
7770

7871
// test results reporter to use
7972
// possible values: 'dots', 'progress'
8073
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
81-
reporters: ["mocha", "coverage", "junit", "json-to-file"],
74+
reporters: ["mocha", "coverage", "junit"],
8275

8376
coverageReporter: {
8477
// specify a common output directory
@@ -101,11 +94,6 @@ module.exports = function (config) {
10194
properties: {}, // key value pair of properties to add to the <properties> section of the report
10295
},
10396

104-
jsonToFileReporter: {
105-
filter: jsonRecordingFilterFunction,
106-
outputPath: ".",
107-
},
108-
10997
// web server port
11098
port: 9876,
11199

@@ -142,9 +130,6 @@ module.exports = function (config) {
142130
browserNoActivityTimeout: 600000,
143131
browserDisconnectTimeout: 10000,
144132
browserDisconnectTolerance: 3,
145-
browserConsoleLogOptions: {
146-
terminal: !isRecordMode(),
147-
},
148133

149134
client: {
150135
mocha: {

0 commit comments

Comments
 (0)