Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Featur/fixacs #284

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"program": "${workspaceFolder}/system/dist/index.js",
"args": [
"serve",
"${workspaceFolder}/system/package/test.yaml"
"${workspaceFolder}/test.yaml"
],
"envFile": "${workspaceFolder}/.env",
"env": {
Expand Down
4 changes: 4 additions & 0 deletions ingredient/ingredient-acs/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src/
.vscode/
package/
test/
5 changes: 5 additions & 0 deletions ingredient/ingredient-acs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

69 changes: 69 additions & 0 deletions ingredient/ingredient-acs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
## Follow these basic steps to setup a new ingredient project:

1. Copy the ingredient-template folder into a new location

a. If creating an HCHB offical ingredient, that should be copied into the ingredient root folder, and renamed approriately.

2. Modify the package.json file and fill out at least the name, which should be a unique npm package.

a. If an offical HCHB ingredient, should be under the @azbake/ moniker

3. Run `npm install` in the new ingredient folder.

4. Modify src/index.ts and set the NS properties for the types you are developing.

a. Functions should set a functiosNS property to the namespace you want to use, as well as set functions to your functions objet.

b. A Plugin should set pluginNS to your unique plugin namespace, along with the plugin object.

c. You can define one, or both.

5. Define either your plugin or function code and then run `npm run compile`, to make sure everything compiles.

6. When you are ready to publish to an NPM repository, you can run `npm run upload`. This will compile, package, version, and publish. You must be logged into the npm repo before executing this for the publish to work.

a. If developing for our mono-repo offical ingredients. You can not self publish. Instead submit a Pull Request with just your ingredient changes. If accepted it will get auto versioned and published.

## Understanding BakeVariables

Bake.yaml recipe files support a concept of expressions. These are specially formatted string values which describe sandboxed javascript to execute and resolve a value. BakeVariables are used for all variable, and parameter based fields in the recipe; as well as other properties when noted.

Within a plugin, or a function object, you must resolve a property directly if it's a `BakeVariable`, otherwise you will not access the correct value. Resolving a BakeVariable requires the current deployment execution context so that the right resolution can happen:

```js
//ingredient property source is a BakeVairbale. We call BakeVariable.value(ctx) to return
//the correct resolved value so we can use it.
let source: string = this._ingredient.properties.source.value(this._ctx)
```

## Developing a plugin ingredient

A plugin ingredient must extend `BaseIngredient` from "@azbake/core". It must also implement:

```javascript
public async Execute(): Promise<void>{}
```

Within your execute method you have access to the current deployment context, which implements `DeploymentContext` from "@azbake/core"

```js
this._ctx
```
This will give you access to things like the logger (which is context aware of current region/ingredient/etc.), the bake package config, environment variables (minus login credentials), The current region for the execution (if needed around primary/secondary ingredient logic), The current azure `AuthToken` that can be passed to Azure APIs, as well as the current `Ingredient` object which contains the parameters:

```js
this._ingredient.properties.parameters
this._ingredient.properties.source
```

*note: source and parameter values are BakeVariables and must be resolved with the current context*

Your plugin will execute with an isolated context for each region that should be deployed ast the environment level, and once for every entry in the bake.yaml file for the recipe.

You can also access function objects of any referenced ingredients from the recipe. `CoreUtils` is always avalible to a recipe, even if not directly included.

```js
let util = IngredientManager.getIngredientFunction("coreutils", this._ctx)

```

78 changes: 78 additions & 0 deletions ingredient/ingredient-acs/create-ingredient-quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Quick Start: Create a new ingredient that deploys an ARM template

In this quickstart, you setup your development environment and create a new ingredient that deploys an ARM template.

1. Clone the Azure Bake repo if you haven't already.
2. Copy the ingredient-template folder as a subfolder of the ingredient folder.
3. Rename the copied folder using your new ingredient name.
4. Create a new arm.json file.
5. Define your ARM template within the arm.json file.
6. Modify plugin.ts to deploy the ARM template. Change MyCustomPlugIn name to reflect the name of your ingredient. ie. AppInsightsPlugIn.

```js
import { BaseIngredient, IngredientManager } from "@azbake/core"
import { ARMHelper } from "@azbake/arm-helper"
import ARMTemplate from "./arm.json"

export class MyCustomPlugin extends BaseIngredient {
public async Execute(): Promise<void> {
try {
let util = IngredientManager.getIngredientFunction("coreutils", this._ctx)
this._logger.log('Custom Plugin Logging: ' + this._ingredient.properties.source)

const helper = new ARMHelper(this._ctx);

let params:any={}
params["parameterName1"]="parameterValue1"
params["parameterName2"]="parameterValue2"
await helper.DeployTemplate(this._name, ARMTemplate, params, await util.resource_group())

} catch(error){
this._logger.error('deployment failed: ' + error)
throw error
}
}
}
```

7. Edit package.json in your ingredient folder
- Set the name, description, version number, and author for your ingredient.
```json
"name": "@azbake/ingredient-app-insights",
"description": "Ingredient for deploying an instance of an Application Insights resource",
"version": "0.0.1",
"author": "HCHB",
```
8. Move /src/tsconfig.json to the parent directory (your ingredient's directory).
9. Modify tsconfig.json's compiler options to reflect the directory change for outDir and add two additional compiler options.
```json
"outDir": "./dist",
..
"resolveJsonModule": true,
"esModuleInterop": true
```

10. Modify index.ts
- Replace MyCustomPlugIn with the plug-in used in plugin.ts
- Replace the plugin namespace to be the same name used in package.json. Example -
```ts
exports.pluginNS = "@azbake/ingredient-app-insights"
```
11. Open a terminal window
12. Navigate to your new ingredient's directory.
13. Install packages as defined in package.json
```bash
npm install
```
14. Compile your new ingredient
```bash
npm run compile
```bash
15. Package your ingredient
```bash
npm pack
```

## Next Steps
In this quick start, you created a simple ingredient that deploys an ARM template and configured your development environment. As a next step, try using your ingredient in a recipe and deploying to Azure (quick start coming soon).
35 changes: 35 additions & 0 deletions ingredient/ingredient-acs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@azbake/ingredient-acs",
"description": "Ingredient for managing Azure Communications Service",
"version": "0.0.1",
"main": "dist/index.js",
"typings": "src/index.ts",
"author": "HCHB",
"license": "",
"scripts": {
"upload": "tsc -p . && npm --no-git-tag-version version patch && npm publish --access public",
"compile": "tsc -p .",
"watch": "tsc -w -p ."
},
"directories": {
"lib": "dist"
},
"peerDependencies": {
"@azbake/core": "*",
"@azure/ms-rest-nodeauth": "*"
},
"devDependencies": {
"@types/node": "^10.12.18",
"@azure/ms-rest-nodeauth": "^3.0.0"
},
"dependencies": {
"@azbake/arm-helper": "^0.1.109",
"@azure/arm-communication" : "^3.0.1",
"@azbake/core": "^0.1.107",
"@azure/identity": "^2.0.4"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
}
}
32 changes: 32 additions & 0 deletions ingredient/ingredient-acs/src/acs-arm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceName": {
"type": "string",
"metadata": {
"description": "The name of the Managed Cluster resource."
}
},
"location": {
"type": "string",
"defaultValue": "global",
"metadata": {
"description": "The Azure location of the AKS resource."
}}
},
"variables": {
},
"resources": [
{
"type": "Microsoft.Communication/CommunicationServices",
"apiVersion": "2022-07-01-preview",
"name": "[parameters('resourceName')]",
"location": "[parameters('location')]",
"tags": {},
"properties": {
"dataLocation": "United States"
}
}
]
}
51 changes: 51 additions & 0 deletions ingredient/ingredient-acs/src/functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {BaseUtility, IngredientManager} from '@azbake/core'
import {CommunicationServiceManagementClient} from '@azure/arm-communication'
import { DefaultAzureCredential, ClientSecretCredential,ChainedTokenCredential } from "@azure/identity";
export class AcsUtils extends BaseUtility {

private token = new ClientSecretCredential(this.context.AuthToken.domain, this.context.AuthToken.clientId, this.context.AuthToken.secret);
private credential = new ChainedTokenCredential(this.token, new DefaultAzureCredential());

public create_resource_name(): string {
let util = IngredientManager.getIngredientFunction("coreutils", this.context)
const st_profile = util.create_resource_name("", null, false);
return st_profile;
}

public async get_primary_connectionstring(name: string, rg: string | null = null) : Promise<string> {

let util = IngredientManager.getIngredientFunction("coreutils", this.context)
let resource_group = rg || await util.resource_group()

const client = new CommunicationServiceManagementClient(this.credential, this.context.Environment.authentication.subscriptionId);

let response = await client.communicationService.listKeys(resource_group, name)

let key: string = ""
if (response.primaryConnectionString)
{
key = response.primaryConnectionString || ""
}
return key
}

public async get_secondary_connectionstring(name: string, rg: string | null = null) : Promise<string> {

let util = IngredientManager.getIngredientFunction("coreutils", this.context)
let resource_group = rg || await util.resource_group()

const client = new CommunicationServiceManagementClient(this.credential, this.context.Environment.authentication.subscriptionId);

let response = await client.communicationService.listKeys(resource_group, name)

let key: string = ""
if (response.secondaryConnectionString)
{
key = response.secondaryConnectionString || ""
}
return key
}


}

10 changes: 10 additions & 0 deletions ingredient/ingredient-acs/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {AcsPlugin} from './plugin'
import {AcsUtils} from './functions'

/* comment out these entries if you are not including an ingredient plugin runner*/
exports.plugin = AcsPlugin
exports.pluginNS = "@azbake/ingredient-acs" //name of the ingredient to reference in a bake.yaml recipe

/* comment out these entries if you are not including a set of expression functions*/
exports.functions = AcsUtils
exports.functionsNS = "acsutils" //bake.yaml expressions can access your functions via "myutils.my_function()"
29 changes: 29 additions & 0 deletions ingredient/ingredient-acs/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { BaseIngredient, IngredientManager,IIngredient,DeploymentContext } from "@azbake/core"
import { ARMHelper } from "@azbake/arm-helper"
import ARMTemplate from "./acs-arm.json"

export class AcsPlugin extends BaseIngredient {
constructor(name: string, ingredient: IIngredient, ctx: DeploymentContext) {
super(name, ingredient, ctx);
this._helper = new ARMHelper(this._ctx);
}

_helper: ARMHelper;

public async Execute(): Promise<void> {
try {
let util = IngredientManager.getIngredientFunction("coreutils", this._ctx)
this._logger.log('Custom Plugin Logging: ' + this._ingredient.properties.source)
let params = await this._helper.BakeParamsToARMParamsAsync(this._name, this._ingredient.properties.parameters)

await this._helper.DeployTemplate(this._name, ARMTemplate, params, await util.resource_group())
} catch(error){
this._logger.error('deployment failed: ' + error)
throw error
}
}
}




25 changes: 25 additions & 0 deletions ingredient/ingredient-acs/test/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: ACS Test
shortName: acs
version: 0.1.0
ingredients:
- "@azbake/ingredient-acs@~0"
- "@azbake/ingredient-null@~0"
resourceGroup: true
#rgOverride: ""
variables:
recipe:
acs-create:
properties:
type: "@azbake/ingredient-acs"
source: ./arm.json
parameters:
resourceName: "[acsutils.create_resource_name()]"
acs-strings:
properties:
type: "@azbake/ingredient-null"
condition: "[coreutils.current_region_primary()]"
parameters:
primaryConnectionString: "[acsutils.get_primary_connectionstring( parameters['resourceName'], await coreutils.resource_group())]"
dependsOn:
- acs-create

14 changes: 14 additions & 0 deletions ingredient/ingredient-acs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"declaration": true,
"outDir": "./dist",
"strict": true,
"stripInternal": true,
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true
},
"include": ["**/*.ts"],
}
2 changes: 1 addition & 1 deletion ingredient/ingredient-functions/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ingredient/ingredient-network-interface/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading