From 11de94e4aea6e047581ce4ef041ca0e5ea3870e2 Mon Sep 17 00:00:00 2001 From: Richard Park Date: Tue, 10 Sep 2019 11:40:32 -0700 Subject: [PATCH] Adding in sample code for AppConfiguration --- .../app-configuration/README.md | 12 +++--- .../app-configuration/package.json | 1 + .../app-configuration/samples/helloworld.ts | 41 +++++++++++++++++++ .../samples/helloworldWithLabels.ts | 36 ++++++++++++++++ .../app-configuration/samples/index.ts | 7 ++++ .../samples/sampleHelpers.ts | 22 ++++++++++ .../app-configuration/src/index.ts | 6 +++ .../app-configuration/test/index.spec.ts | 5 +-- .../app-configuration/test/samples.spec.ts | 7 ++++ .../app-configuration/test/testhelpers.ts | 10 +++++ 10 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 sdk/appconfiguration/app-configuration/samples/helloworld.ts create mode 100644 sdk/appconfiguration/app-configuration/samples/helloworldWithLabels.ts create mode 100644 sdk/appconfiguration/app-configuration/samples/index.ts create mode 100644 sdk/appconfiguration/app-configuration/samples/sampleHelpers.ts create mode 100644 sdk/appconfiguration/app-configuration/test/samples.spec.ts create mode 100644 sdk/appconfiguration/app-configuration/test/testhelpers.ts diff --git a/sdk/appconfiguration/app-configuration/README.md b/sdk/appconfiguration/app-configuration/README.md index 0a4e89bfd7c4..289df855dfe9 100644 --- a/sdk/appconfiguration/app-configuration/README.md +++ b/sdk/appconfiguration/app-configuration/README.md @@ -1,6 +1,10 @@ # Azure App Configuration client library for JS -This package contains an isomorphic SDK for ConfigurationClient. +Azure App Configuration is a managed service that helps developers centralize their application configurations simply and securely. + +Modern programs, especially programs running in a cloud, generally have many components that are distributed in nature. Spreading configuration settings across these components can lead to hard-to-troubleshoot errors during an application deployment. Use App Configuration to securely store all the settings for your application in one place. + +Use the client library for App Configuration to create and manage application configuration settings. ## Getting started @@ -12,7 +16,7 @@ This package contains an isomorphic SDK for ConfigurationClient. ### How to Install ```bash -npm install @azure/app-config +npm install @azure/app-configuration ``` ## Key concepts @@ -31,10 +35,8 @@ npm install @azure/ms-rest-nodeauth ##### Sample code ```typescript -import * as coreHttp from "@azure/core-http"; -import * as coreArm from "@azure/core-arm"; import * as msRestNodeAuth from "@azure/ms-rest-nodeauth"; -import { ConfigurationClient, ConfigurationModels, ConfigurationMappers } from "@azure/app-config"; +import { ConfigurationClient, ConfigurationModels, ConfigurationMappers } from "@azure/app-configuration"; const subscriptionId = process.env["AZURE_SUBSCRIPTION_ID"]; msRestNodeAuth.interactiveLogin().then((creds) => { diff --git a/sdk/appconfiguration/app-configuration/package.json b/sdk/appconfiguration/app-configuration/package.json index 2c56dabfa7af..cd3578967948 100644 --- a/sdk/appconfiguration/app-configuration/package.json +++ b/sdk/appconfiguration/app-configuration/package.json @@ -80,6 +80,7 @@ "prebuild": "npm run clean", "pack": "npm pack 2>&1", "test": "npm run build:test && mocha -t 1200000 test-dist/index.node.js --reporter mocha-multi --reporter-options spec=-,mocha-junit-reporter=-", + "test:watch": "mocha \"test/**/*\" -t 1200000 --require ts-node/register --watch-extensions ts,tsx --reporter mocha-multi --reporter-options spec=-,mocha-junit-reporter=- --watch", "unit-test:browser": "echo skipped", "unit-test:node": "echo skipped", "unit-test": "npm run unit-test:node && npm run unit-test:browser" diff --git a/sdk/appconfiguration/app-configuration/samples/helloworld.ts b/sdk/appconfiguration/app-configuration/samples/helloworld.ts new file mode 100644 index 000000000000..772fb3afb900 --- /dev/null +++ b/sdk/appconfiguration/app-configuration/samples/helloworld.ts @@ -0,0 +1,41 @@ +import { getConnectionStringFromEnvironment, deleteKeyAndLabels } from "./sampleHelpers"; + +// NOTE: replace with import { AppConfigurationClient } from "@azure/app-configuration" +// in a standalone project +import { AppConfigurationClient } from "../src" + +export async function run() { + console.log("Running helloworld sample"); + + let connectionString = getConnectionStringFromEnvironment(); + const client = new AppConfigurationClient(connectionString); + + const greetingKey = "Samples:Greeting"; + + deleteKeyAndLabels([greetingKey], client); + + // creating a new setting + console.log(`Adding in new setting ${greetingKey}`); + await client.addConfigurationSetting(greetingKey, { value: "Hello!" }); + + const newSetting = await client.getConfigurationSetting(greetingKey); + console.log(`${greetingKey} has been set to ${newSetting.value}`); + + // changing the value of a setting + await client.setConfigurationSetting(greetingKey, { value: "Goodbye!" }); + + const updatedSetting = await client.getConfigurationSetting(greetingKey); + console.log(`${greetingKey} has been set to ${updatedSetting.value}`); + + // removing the setting + await client.deleteConfigurationSetting(greetingKey, {}); + console.log(`${greetingKey} has been deleted`); + + deleteKeyAndLabels([greetingKey], client); +} + +// If you want to run this sample from a console +// uncomment these lines so run() will get called +// run().catch(err => { +// console.log(`ERROR: ${err}`); +// }); \ No newline at end of file diff --git a/sdk/appconfiguration/app-configuration/samples/helloworldWithLabels.ts b/sdk/appconfiguration/app-configuration/samples/helloworldWithLabels.ts new file mode 100644 index 000000000000..502ec43b6b65 --- /dev/null +++ b/sdk/appconfiguration/app-configuration/samples/helloworldWithLabels.ts @@ -0,0 +1,36 @@ +import { getConnectionStringFromEnvironment, deleteKeyAndLabels } from "./sampleHelpers"; + +// NOTE: replace with import { AppConfigurationClient } from "@azure/app-configuration" +// in a standalone project +import { AppConfigurationClient } from "../src" + +export async function run() { + console.log("Running helloworldWithLabels sample"); + + let connectionString = getConnectionStringFromEnvironment(); + const client = new AppConfigurationClient(connectionString); + + const urlKey = "Samples:Endpoint:Url"; + + deleteKeyAndLabels([urlKey], client); + + // labels allow you to use the same key with different values for separate environments + // or clients + console.log("Adding in endpoint with two labels - beta and production"); + await client.addConfigurationSetting(urlKey, { label: "beta", value: "https://beta.example.com" }); + await client.addConfigurationSetting(urlKey, { label: "production", value: "https://example.com" }); + + const betaEndpoint = await client.getConfigurationSetting(urlKey, { label: "beta" }); + console.log(`Endpoint with beta label: ${betaEndpoint.value}`); + + const productionEndpoint = await client.getConfigurationSetting(urlKey, { label: "production" }); + console.log(`Endpoint with production label: ${productionEndpoint.value}`); + + deleteKeyAndLabels([urlKey], client); +} + +// If you want to run this sample from a console +// uncomment these lines so run() will get called +// run().catch(err => { +// console.log(`ERROR: ${err}`); +// }); \ No newline at end of file diff --git a/sdk/appconfiguration/app-configuration/samples/index.ts b/sdk/appconfiguration/app-configuration/samples/index.ts new file mode 100644 index 000000000000..d768fc0d0d6b --- /dev/null +++ b/sdk/appconfiguration/app-configuration/samples/index.ts @@ -0,0 +1,7 @@ +import * as helloworld from "./helloworld"; +import * as helloworldWithLabels from "./helloworldWithLabels"; + +export async function runAll() { + await helloworld.run(); + await helloworldWithLabels.run(); +} \ No newline at end of file diff --git a/sdk/appconfiguration/app-configuration/samples/sampleHelpers.ts b/sdk/appconfiguration/app-configuration/samples/sampleHelpers.ts new file mode 100644 index 000000000000..1100c1349663 --- /dev/null +++ b/sdk/appconfiguration/app-configuration/samples/sampleHelpers.ts @@ -0,0 +1,22 @@ +import { AppConfigurationClient } from "../src" + +export function getConnectionStringFromEnvironment() : string { + const connectionString = process.env["AZ_CONFIG_CONNECTION"]!; + + if (connectionString == null) { + throw Error(`No connection string in environment - set AZ_CONFIG_CONNECTION with a connection string for your AppConfiguration instance.`); + } + + return connectionString; +} + +export async function deleteKeyAndLabels(keys: string[], client: AppConfigurationClient) { + const existingSettings = await client.listConfigurationSettings({ + key: keys + }); + + for (const setting of existingSettings) { + console.log(`Removing key ${setting.key} (and all labels)`); + await client.deleteConfigurationSetting(setting.key!, { label: setting.label }); + } +} \ No newline at end of file diff --git a/sdk/appconfiguration/app-configuration/src/index.ts b/sdk/appconfiguration/app-configuration/src/index.ts index f1aa1b606567..bd815dcaa3ab 100644 --- a/sdk/appconfiguration/app-configuration/src/index.ts +++ b/sdk/appconfiguration/app-configuration/src/index.ts @@ -102,6 +102,12 @@ export class AppConfigurationClient { */ constructor(uri: string, credential: TokenCredential); constructor(uriOrConnectionString: string, credential?: TokenCredential) { + if (uriOrConnectionString == null) { + throw new Error( + "You must provide a connection string or the URL for your AppConfiguration instance" + ); + } + const regexMatch = uriOrConnectionString.match(ConnectionStringRegex); if (regexMatch) { const credential = new AppConfigCredential(regexMatch[2], regexMatch[3]); diff --git a/sdk/appconfiguration/app-configuration/test/index.spec.ts b/sdk/appconfiguration/app-configuration/test/index.spec.ts index aa80f2f00770..8beae14eded8 100644 --- a/sdk/appconfiguration/app-configuration/test/index.spec.ts +++ b/sdk/appconfiguration/app-configuration/test/index.spec.ts @@ -2,6 +2,7 @@ // Licensed under the MIT License. import * as assert from "assert"; +import { getConnectionString } from "./testhelpers"; import * as dotenv from "dotenv"; import { AppConfigurationClient } from "../src"; @@ -14,9 +15,7 @@ describe("AppConfigurationClient", () => { let client: AppConfigurationClient; before("validate environment variables", () => { - if (!connectionString) { - throw new Error("APPCONFIG_CONNECTION_STRING not defined."); - } + let connectionString = getConnectionString(); client = new AppConfigurationClient(connectionString); }); diff --git a/sdk/appconfiguration/app-configuration/test/samples.spec.ts b/sdk/appconfiguration/app-configuration/test/samples.spec.ts new file mode 100644 index 000000000000..c594b699408a --- /dev/null +++ b/sdk/appconfiguration/app-configuration/test/samples.spec.ts @@ -0,0 +1,7 @@ +import { runAll } from "../samples"; + +describe("AppConfiguration samples", () => { + it("Make sure all the samples build and run", async () => { + await runAll(); + }); +}); \ No newline at end of file diff --git a/sdk/appconfiguration/app-configuration/test/testhelpers.ts b/sdk/appconfiguration/app-configuration/test/testhelpers.ts new file mode 100644 index 000000000000..9ef374e842a7 --- /dev/null +++ b/sdk/appconfiguration/app-configuration/test/testhelpers.ts @@ -0,0 +1,10 @@ +import * as assert from "assert"; +import * as dotenv from "dotenv"; + +dotenv.config(); + +export function getConnectionString() { + let connectionStringFromEnvironment = process.env["APPCONFIG_CONNECTION_STRING"]!; + assert.ok(connectionStringFromEnvironment, "Connection string not set in environment variable APPCONFIG_CONNECTION_STRING"); + return connectionStringFromEnvironment; +} \ No newline at end of file