Skip to content

Commit

Permalink
Add support for add-on services
Browse files Browse the repository at this point in the history
  • Loading branch information
amitkma committed Apr 29, 2024
1 parent 4e5e99a commit e2a73e8
Show file tree
Hide file tree
Showing 7 changed files with 1,743 additions and 2,195 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Azure Container Apps Build and Deploy

_This repo extends the existing action to fix upstream issues and allow experimental features such as [add-on services](https://learn.microsoft.com/en-us/azure/container-apps/services)._

This action allows users to easily deploy their application source to an
[Azure Container App](https://azure.microsoft.com/en-us/services/container-apps/) in their GitHub workflow by either
providing a previously built image, a Dockerfile that an image can be built from, or using a builder to create a
Expand Down Expand Up @@ -177,6 +179,13 @@ For more information on the structure of the YAML configuration file, please vis
| `environmentVariables` | No | A list of environment variable(s) for the container. Space-separated values in 'key=value' format. Empty string to clear existing values. Prefix value with 'secretref:' to reference a secret. |
| `ingress` | No | Possible options: external, internal, disabled. If set to "external" (default value if not provided when creating a Container App), the Container App will be visible from the internet or a VNET, depending on the app environment endpoint configured. If set to "internal", the Container App will be visible from within the app environment only. If set to "disabled", ingress will be disabled for this Container App and will not have an HTTP or TCP endpoint. |
| `disableTelemetry` | No | If set to `true`, no telemetry will be collected by this GitHub Action. If set to `false`, or if this argument is not provided, telemetry will be sent to Microsoft about the Container App build and deploy scenario targeted by this GitHub Action. |
| `kafka` | No | Name of kafka add-on service that will be created and bounded to the container. Multiple add-on service of this type can be created by specifying a comma-separated or newline-separated list. For example: `mykafka` or `mykafka-1,mykafka-2` |
| `postgres` | No | Name of postgres add-on service that will be created and bounded to the container. Multiple add-on service of this type can be created by specifying a comma-separated or newline-separated list. For example: `mypostgres` or `mypostgres-1,mypostgres-2` |
| `mariadb` | No | Name of mariadb add-on service that will be created and bounded to the container. Multiple add-on service of this type can be created by specifying a comma-separated or newline-separated list. For example: `mymariadb` or `mymariadb-1,mymariadb-2` |
| `redis` | No | Name of redis add-on service that will be created and bounded to the container. Multiple add-on service of this type can be created by specifying a comma-separated or newline-separated list. For example: `myredis` or `myredis-1,myredis-2` |
| `qdrant` | No | Name of qdrant add-on service that will be created and bounded to the container. Multiple add-on service of this type can be created by specifying a comma-separated or newline-separated list. For example: `myqdrant` or `myqdrant-1,myqdrant-2` |
| `milvus` | No | Name of milvus add-on service that will be created and bounded to the container. Multiple add-on service of this type can be created by specifying a comma-separated or newline-separated list. For example: `mymilvus` or `mymilvus-1,mymilvus-2` |
| `weaviate` | No | Name of weaviate add-on service that will be created and bounded to the container. Multiple add-on service of this type can be created by specifying a comma-separated or newline-separated list. For example: `myweaviate` or `myweaviate-1,myweaviate-2` |

## Usage

Expand Down
39 changes: 37 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,42 @@ inputs:
this GitHub Action.'
required: false
default: false
kafka:
description: |
'Name of kafka add-on service that will be created and bounded to the container.
Multiple add-on service of this type can be created by specifying a omma-separated or newline-separated list.'
required: false
mariadb:
description: |
'Name of mariadb add-on service that will be created and bounded to the container.
Multiple add-on service of this type can be created by specifying a omma-separated or newline-separated list.'
required: false
postgres:
description: |
'Name of postgres add-on service that will be created and bounded to the container.
Multiple add-on service of this type can be created by specifying a omma-separated or newline-separated list.'
required: false
milvus:
description: |
'Name of milvus add-on service that will be created and bounded to the container.
Multiple add-on service of this type can be created by specifying a omma-separated or newline-separated list.'
required: false
qdrant:
description: |
'Name of qdrant add-on service that will be created and bounded to the container.
Multiple add-on service of this type can be created by specifying a omma-separated or newline-separated list.'
required: false
redis:
description: |
'Name of redis add-on service that will be created and bounded to the container.
Multiple add-on service of this type can be created by specifying a omma-separated or newline-separated list.'
required: false
weaviate:
description: |
'Name of weaviate add-on service that will be created and bounded to the container.
Multiple add-on service of this type can be created by specifying a omma-separated or newline-separated list.'
required: false

runs:
using: 'node16'
main: 'dist/index.js'
using: "node20"
main: "dist/index.js"
48 changes: 48 additions & 0 deletions azurecontainerapps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ContainerRegistryHelper } from './src/ContainerRegistryHelper';
import { TelemetryHelper } from './src/TelemetryHelper';
import { Utility } from './src/Utility';
import { GitHubActionsToolHelper } from './src/GitHubActionsToolHelper';
import { AddOnServicesHelper } from './src/AddOnServicesHelper';

const buildArgumentRegex = /"[^"]*"|\S+/g;
const buildpackEnvironmentNameRegex = /^"?(BP|ORYX)_[-._a-zA-Z0-9]+"?$/
Expand Down Expand Up @@ -101,6 +102,7 @@ export class azurecontainerapps {
private static registryHelper: ContainerRegistryHelper;
private static util: Utility;
private static toolHelper: GitHubActionsToolHelper;
private static addOnHelper: AddOnServicesHelper

// Miscellaneous properties
private static imageToBuild: string;
Expand All @@ -111,6 +113,9 @@ export class azurecontainerapps {
private static useInternalRegistry: boolean;
private static shouldCreateOrUpdateContainerAppWithUp: boolean;

private static addOnTypes = ['kafka', 'mariadb', 'milvus', 'postgres', 'qdrant', 'redis', 'weaviate']
private static addOnServices: string[]

/**
* Initializes the helpers used by this task.
* @param disableTelemetry - Whether or not to disable telemetry for this task.
Expand Down Expand Up @@ -138,6 +143,9 @@ export class azurecontainerapps {

// Set up ContainerRegistryHelper for managing calls around the Container Registry
this.registryHelper = new ContainerRegistryHelper();

// Set up AddOnServicesHelper for managing add-on services
this.addOnHelper = new AddOnServicesHelper();
}

/**
Expand Down Expand Up @@ -234,6 +242,8 @@ export class azurecontainerapps {
if (!this.containerAppExists) {
this.containerAppEnvironment = await this.getOrCreateContainerAppEnvironment(this.containerAppName, this.resourceGroup, this.location);
}

this.addOnServices = await this.createAddOnServices(this.containerAppName, this.resourceGroup, this.containerAppEnvironment);
}

/**
Expand Down Expand Up @@ -325,6 +335,38 @@ export class azurecontainerapps {
return resourceGroup;
}

/**
* Create add-on services if required. A name for the service is generated by prefixing the given
* service name with container name. For example, if you have given redis add-on service "myredis" name,
* then the actual service name will be generated in the form '<containerAppName>-<addon-type>-myredis'.
*
* This is done to ensure that we have only one add-on service of a type for a given container.
*
* @param containerAppName - The name of the Container App to use for the task.
* @param resourceGroup - The name of the resource group to use for the task.
* @param environment - the Container App Environment that will be associated with the add-on
* @returns The name of the Container App Environment to use for the task.
*/
private static async createAddOnServices(containerAppName: string, resourceGroup: string, environment: string): Promise<string[]> {
let createdServices: string[] = []

for (const addOn in this.addOnTypes){
let services = this.toolHelper.getInput(addOn, false)

if (!this.util.isNullOrEmpty(services)){

let bindings = this.util.parseServices(services)

for (const binding in bindings) {
let bindingName = `${containerAppName}-${addOn}-${binding}`
await this.addOnHelper.createAddOnService(addOn, bindingName, resourceGroup, environment)
createdServices.push(bindingName)
}
}
}
return createdServices
}

/**
* Gets the name of the Container App Environment to use for the task. If the 'containerAppEnvironment' argument
* is not provided, then the task will attempt to discover an existing Container App Environment in the resource
Expand Down Expand Up @@ -571,6 +613,12 @@ export class azurecontainerapps {
`--registry-password ${this.registryPassword}`);
}

if (!(this.addOnServices === null || this.addOnServices === undefined || this.addOnServices.length == 0)){
for (const addOnService in this.addOnServices){
this.commandLineArgs.push(`--bind ${addOnService}`)
}
}

// Determine default values only for the 'create' scenario to avoid overriding existing values for the 'update' scenario
if (!this.containerAppExists) {
this.ingressEnabled = true;
Expand Down
Loading

0 comments on commit e2a73e8

Please sign in to comment.