Skip to content
Merged
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"terraform:cleanup": "rimraf ./tests/terraform/{.terraform,.terraform.lock.hcl,tfplan} ./tests/terraform/*.{tfstate,tfplan,backup}"
},
"dependencies": {
"@azure/arm-appcontainers": "^2.0.0",
"@azure/arm-appinsights": "^4.0.0",
"@azure/arm-appservice": "^11.0.0",
"@azure/arm-authorization": "^8.4.1",
Expand Down
4 changes: 4 additions & 0 deletions src/enums/serviceMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import AzureCdnOrigins from '../services/cdnOrigins'
import AzureCdnProfiles from '../services/cdnProfiles'
import AzureCognitiveServicesAccount from '../services/cognitiveServicesAccount'
import AzureContainerRegistry from '../services/containerRegistry'
import AzureContainerApp from '../services/containerApp'
import AzureContainerAppEnvironment from '../services/containerAppEnvironment'
import AzureDataCollectionRule from '../services/dataCollectionRule'
import AzureDataFactory from '../services/dataFactory'
import AzureDatabaseManagedSqlInstance from '../services/databaseManagedSqlInstance'
Expand Down Expand Up @@ -131,6 +133,8 @@ export default {
[services.cdnProfiles]: AzureCdnProfiles,
[services.cognitiveServicesAccount]: AzureCognitiveServicesAccount,
[services.containerRegistry]: AzureContainerRegistry,
[services.containerApp]: AzureContainerApp,
[services.containerAppEnvironment]: AzureContainerAppEnvironment,
[services.cosmosDb]: AzureCosmosDb,
[services.dataCollectionRule]: AzureDataCollectionRule,
[services.dataFactory]: AzureDataFactory,
Expand Down
2 changes: 2 additions & 0 deletions src/enums/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export default {
cdnProfiles: 'cdnProfiles',
cognitiveServicesAccount: 'cognitiveServicesAccount',
containerRegistry: 'containerRegistry',
containerApp: 'containerApp',
containerAppEnvironment: 'containerAppEnvironment',
cosmosDb: 'cosmosDb',
dataCollectionRule: 'dataCollectionRule',
dataFactory: 'dataFactory',
Expand Down
3 changes: 3 additions & 0 deletions src/properties/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ export default {
`Found ${num} CDN origin groups`,
foundContainerRegistries: (num: number): string =>
`Found ${num} container registries`,
foundContainerApps: (num: number): string => `Found ${num} container apps`,
foundContainerAppEnvironment: (num: number): string =>
`Found ${num} container environments`,
/* Cosmos DB */
foundCosmosDbAccounts: (num: number): string =>
`Found ${num} cosmos DB accounts`,
Expand Down
76 changes: 76 additions & 0 deletions src/services/containerApp/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { ContainerApp, ContainerAppsAPIClient } from '@azure/arm-appcontainers'

import CloudGraph from '@cloudgraph/sdk'

import azureLoggerText from '../../properties/logger'
import { AzureServiceInput, TagMap } from '../../types'
import { tryCatchWrapper } from '../../utils/index'
import { regionMap } from '../../enums/regions'

const { logger } = CloudGraph
const lt = { ...azureLoggerText }
const serviceName = 'ContainerApp'

export interface RawAzureContainerApp
extends Omit<ContainerApp, 'location' | 'tags'> {
resourceGroupId?: string
region: string
customDomainVerificationId?: string
environmentId?: string
latestReadyRevisionName?: string
latestRevisionFqdn?: string
latestRevisionName?: string
location?: string
managedEnvironmentId?: string
provisioningState?: string
workloadProfileName?: string
Tags: TagMap
}

export default async ({
config,
}: AzureServiceInput): Promise<{
[property: string]: RawAzureContainerApp[]
}> => {
try {
const { tokenCredentials, subscriptionId } = config
const client = new ContainerAppsAPIClient(tokenCredentials, subscriptionId)

const containerApps: RawAzureContainerApp[] = []
const result = { global: [] }
await tryCatchWrapper(
async () => {
for await (const containerApp of client.containerApps.listBySubscription()) {
if (containerApp) {
const { tags, ...rest } = containerApp

containerApps.push({
...rest,
id: rest.id.replace('/containerapps/', '/containerApps/'), // fix casing in Id
region: containerApp.location || regionMap.global,
Tags: tags || {},
})
}
}
},
{
service: serviceName,
client,
scope: 'containerApps',
operation: 'listBySubscription',
}
)
logger.debug(lt.foundContainerApps(containerApps.length))

containerApps.map(({ region, ...rest }) => {
result.global.push({
...rest,
region,
})
})
return result
} catch (e) {
logger.error(e)
return {}
}
}
47 changes: 47 additions & 0 deletions src/services/containerApp/format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { RawAzureContainerApp } from './data'
import { formatTagsFromMap } from '../../utils/format'
import { AzureContainerApp } from '../../types/generated'

export default ({
service,
account: subscriptionId,
}: {
service: RawAzureContainerApp
account: string
}): AzureContainerApp => {
const {
id,
name,
type,
region,
resourceGroupId,
customDomainVerificationId,
environmentId,
latestReadyRevisionName,
latestRevisionFqdn,
latestRevisionName,
location,
managedEnvironmentId,
provisioningState,
workloadProfileName,
Tags = {},
} = service
return {
id,
name,
type,
region,
resourceGroupId,
customDomainVerificationId,
environmentId,
latestReadyRevisionName,
latestRevisionFqdn,
latestRevisionName,
location,
managedEnvironmentId,
provisioningState,
workloadProfileName,
subscriptionId,
tags: formatTagsFromMap(Tags),
}
}
13 changes: 13 additions & 0 deletions src/services/containerApp/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Service } from '@cloudgraph/sdk'
import BaseService from '../base'
import format from './format'
import mutation from './mutation'
import getData from './data'

export default class AzureContainerApp extends BaseService implements Service {
format = format.bind(this)

getData = getData.bind(this)

mutation = mutation
}
5 changes: 5 additions & 0 deletions src/services/containerApp/mutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default `mutation($input: [AddazureContainerAppInput!]!) {
addazureContainerApp(input: $input, upsert: true) {
numUids
}
}`
16 changes: 16 additions & 0 deletions src/services/containerApp/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type azureContainerApp implements azureResource
@generate(
query: { get: true, query: true, aggregate: true }
mutation: { add: true, delete: false }
)
@key(fields: "id") {
location: String @search(by: [hash, regexp])
provisioningState: String @search(by: [hash, regexp])
managedEnvironmentId: String @search(by: [hash, regexp])
environmentId: String @search(by: [hash, regexp])
workloadProfileName: String @search(by: [hash, regexp])
latestRevisionName: String @search(by: [hash, regexp])
latestReadyRevisionName: String @search(by: [hash, regexp])
latestRevisionFqdn: String @search(by: [hash, regexp])
customDomainVerificationId: String @search(by: [hash, regexp])
}
179 changes: 179 additions & 0 deletions src/services/containerAppEnvironment/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import {
ContainerAppsAPIClient,
ManagedEnvironment,
Certificate,
DaprComponent,
ManagedEnvironmentStorage,
} from '@azure/arm-appcontainers'

import CloudGraph from '@cloudgraph/sdk'
import azureLoggerText from '../../properties/logger'
import { AzureServiceInput, TagMap } from '../../types'
import { tryCatchWrapper } from '../../utils/index'
import { regionMap } from '../../enums/regions'

const { logger } = CloudGraph
const lt = { ...azureLoggerText }
const serviceName = 'ContainerAppEnvironment'

export interface RawAzureAppEnvironment
extends Omit<ManagedEnvironment, 'location' | 'tags'> {
resourceGroupId?: string
certificates: Certificate[]
daprComponents: DaprComponent[]
storages: ManagedEnvironmentStorage[]
region: string
defaultDomain?: string
eventStreamEndpoint?: string
infrastructureResourceGroup?: string
provisioningState?: string
staticIp?: string
subscriptionId?: string
zoneRedundant?: boolean
Tags: TagMap
}

async function getDaprComponents(
client: ContainerAppsAPIClient,
resourceGroupName: string,
resource: ManagedEnvironment
): Promise<DaprComponent[]> {
const daprComponents = [] as DaprComponent[]
await tryCatchWrapper(
async () => {
for await (const daprComponent of client.daprComponents.list(
resourceGroupName,
resource.name
)) {
daprComponents.push(daprComponent)
}
},
{
service: serviceName,
client,
scope: 'daprComponents',
operation: 'list',
}
)
return daprComponents
}

async function getCertificates(
client: ContainerAppsAPIClient,
resourceGroupName: string,
resource: ManagedEnvironment
): Promise<Certificate[]> {
const certificates = [] as Certificate[]
await tryCatchWrapper(
async () => {
for await (const certificate of client.certificates.list(
resourceGroupName,
resource.name
)) {
certificates.push(certificate)
}
},
{
service: serviceName,
client,
scope: 'certificates',
operation: 'list',
}
)
return certificates
}

async function getStorages(
client: ContainerAppsAPIClient,
resourceGroupName: string,
resource: ManagedEnvironment
): Promise<ManagedEnvironmentStorage[]> {
const storages = [] as ManagedEnvironmentStorage[]
await tryCatchWrapper(
async () => {
const storagesCollection = await client.managedEnvironmentsStorages.list(
resourceGroupName,
resource.name
)
for (const storage of storagesCollection.value) {
storages.push(storage)
}
},
{
service: serviceName,
client,
scope: 'managedEnvironmentsStorages',
operation: 'list',
}
)
return storages
}

export default async ({
config,
}: AzureServiceInput): Promise<{
[property: string]: RawAzureAppEnvironment[]
}> => {
try {
const { tokenCredentials, subscriptionId } = config
const client = new ContainerAppsAPIClient(tokenCredentials, subscriptionId)
const resources: RawAzureAppEnvironment[] = []
const result = { global: [] }
await tryCatchWrapper(
async () => {
for await (const resource of client.managedEnvironments.listBySubscription()) {
if (resource) {
const { tags, ...rest } = resource

// "/subscriptions/xxx/resourceGroups/yyy/providers/Microsoft.App/containerApps/YYY"
const [, , , , resourceGroupName] = resource.id.split('/')
const certificates = await getCertificates(
client,
resourceGroupName,
resource
)

const daprComponents = await getDaprComponents(
client,
resourceGroupName,
resource
)

const storages = await getStorages(
client,
resourceGroupName,
resource
)

resources.push({
...rest,
region: resource.location || regionMap.global,
certificates,
daprComponents,
storages,
Tags: tags || {},
})
}
}
},
{
service: serviceName,
client,
scope: 'managedEnvironments',
operation: 'listBySubscription',
}
)
logger.debug(lt.foundContainerAppEnvironment(resources.length))

resources.map(({ region, ...rest }) => {
result.global.push({
...rest,
region,
})
})
return result
} catch (e) {
logger.error(e)
return {}
}
}
Loading