CI/CD - CodeBuild + CodeDeploy + CodePipeline
This commit is contained in:
@@ -27,3 +27,25 @@ describe('CloudProxyService API Gateway CORS', () => {
|
||||
}}])
|
||||
})
|
||||
})
|
||||
|
||||
describe('CloudProxyService resource lifecycle', () => {
|
||||
test('forwards lifecycle actions to the registered adapter', async () => {
|
||||
const calls: string[] = []
|
||||
const adapter: CloudServiceAdapter = {
|
||||
cloud: 'aws', service: 'apigateway', schema: awsApiGatewaySchema,
|
||||
list: async () => [], get: async () => null, create: async () => ({
|
||||
id: 'api', name: 'api', cloud: 'aws', service: 'apigateway', type: 'rest-api', region: null, createdAt: null, metadata: {},
|
||||
}), delete: async () => {},
|
||||
start: async (id) => { calls.push(`start:${id}`) },
|
||||
stop: async (id) => { calls.push(`stop:${id}`) },
|
||||
reboot: async (id) => { calls.push(`reboot:${id}`) },
|
||||
}
|
||||
const service = new CloudProxyService(new CloudAdapterRegistry([adapter]))
|
||||
|
||||
await service.startResource('aws', 'apigateway', 'api-123')
|
||||
await service.stopResource('aws', 'apigateway', 'api-123')
|
||||
await service.rebootResource('aws', 'apigateway', 'api-123')
|
||||
|
||||
expect(calls).toEqual(['start:api-123', 'stop:api-123', 'reboot:api-123'])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -86,6 +86,9 @@ import type {
|
||||
import {NotSupportedError} from '../cloud-spi/errors'
|
||||
import {CloudAdapterRegistry} from '../registry/CloudAdapterRegistry'
|
||||
import type {StartWorkflowExecutionInput, WorkflowExecutionDetail, WorkflowExecutionHistoryPage, WorkflowExecutionSummary} from '../cloud-spi/workflowExecutions'
|
||||
import type {CodeBuildBuild, StartCodeBuildInput} from '../cloud-spi/codebuild'
|
||||
import type {PipelineExecutionSummary, PipelineState} from '../cloud-spi/codepipeline'
|
||||
import type {CodeDeployDeployment, StartCodeDeployDeploymentInput} from '../cloud-spi/codedeploy'
|
||||
import {SERVICE_CATALOG_ENTRIES, displayNameFor, routeFor} from '../cloud-spi/serviceCatalog'
|
||||
import {toHttpError} from '../cloud-spi/errors'
|
||||
import {mapAwsSdkError} from '../adapter-aws/awsErrors'
|
||||
@@ -482,6 +485,24 @@ export class CloudProxyService {
|
||||
await this.requireAdapter(cloud, service).delete(id)
|
||||
}
|
||||
|
||||
async startResource(cloud: CloudProvider, service: CloudServiceType, id: string): Promise<void> {
|
||||
const adapter = this.requireAdapter(cloud, service)
|
||||
if (!adapter.start) throw new NotSupportedError(`Resource start is not supported for ${cloud}/${service}`)
|
||||
await adapter.start(id)
|
||||
}
|
||||
|
||||
async stopResource(cloud: CloudProvider, service: CloudServiceType, id: string): Promise<void> {
|
||||
const adapter = this.requireAdapter(cloud, service)
|
||||
if (!adapter.stop) throw new NotSupportedError(`Resource stop is not supported for ${cloud}/${service}`)
|
||||
await adapter.stop(id)
|
||||
}
|
||||
|
||||
async rebootResource(cloud: CloudProvider, service: CloudServiceType, id: string): Promise<void> {
|
||||
const adapter = this.requireAdapter(cloud, service)
|
||||
if (!adapter.reboot) throw new NotSupportedError(`Resource reboot is not supported for ${cloud}/${service}`)
|
||||
await adapter.reboot(id)
|
||||
}
|
||||
|
||||
async encryptKms(cloud: CloudProvider, keyId: string, input: KmsEncryptInput): Promise<KmsEncryptResult> {
|
||||
const adapter = this.requireAdapter(cloud, 'kms')
|
||||
if (!adapter.encrypt) throw new NotSupportedError(`${cloud}/kms encrypt is not supported`)
|
||||
@@ -852,6 +873,46 @@ export class CloudProxyService {
|
||||
await this.workflowAdapter(cloud).stopExecution(executionArn)
|
||||
}
|
||||
|
||||
async startCodeBuild(cloud: CloudProvider, projectName: string, input: StartCodeBuildInput): Promise<CodeBuildBuild> {
|
||||
return this.codeBuildAdapter(cloud).startBuild!(projectName, input)
|
||||
}
|
||||
|
||||
async listCodeBuilds(cloud: CloudProvider, projectName: string): Promise<CodeBuildBuild[]> {
|
||||
return this.codeBuildAdapter(cloud).listBuilds!(projectName)
|
||||
}
|
||||
|
||||
async getCodeBuild(cloud: CloudProvider, id: string): Promise<CodeBuildBuild | null> {
|
||||
return this.codeBuildAdapter(cloud).getBuild!(id)
|
||||
}
|
||||
|
||||
async startPipeline(cloud: CloudProvider, id: string): Promise<{id: string}> {
|
||||
return this.codePipelineAdapter(cloud).startPipeline!(id)
|
||||
}
|
||||
|
||||
async listPipelineExecutions(cloud: CloudProvider, id: string): Promise<PipelineExecutionSummary[]> {
|
||||
return this.codePipelineAdapter(cloud).listPipelineExecutions!(id)
|
||||
}
|
||||
|
||||
async getPipelineState(cloud: CloudProvider, id: string): Promise<PipelineState> {
|
||||
return this.codePipelineAdapter(cloud).getPipelineState!(id)
|
||||
}
|
||||
|
||||
async startCodeDeployDeployment(cloud: CloudProvider, applicationName: string, deploymentGroupName: string, input: StartCodeDeployDeploymentInput): Promise<CodeDeployDeployment> {
|
||||
return this.codeDeployAdapter(cloud).startCodeDeployDeployment!(applicationName, deploymentGroupName, input)
|
||||
}
|
||||
|
||||
async listCodeDeployDeployments(cloud: CloudProvider, applicationName: string, deploymentGroupName: string): Promise<CodeDeployDeployment[]> {
|
||||
return this.codeDeployAdapter(cloud).listCodeDeployDeployments!(applicationName, deploymentGroupName)
|
||||
}
|
||||
|
||||
async getCodeDeployDeployment(cloud: CloudProvider, id: string): Promise<CodeDeployDeployment> {
|
||||
return this.codeDeployAdapter(cloud).getCodeDeployDeployment!(id)
|
||||
}
|
||||
|
||||
async stopCodeDeployDeployment(cloud: CloudProvider, id: string, rollback: boolean): Promise<void> {
|
||||
await this.codeDeployAdapter(cloud).stopCodeDeployDeployment!(id, rollback)
|
||||
}
|
||||
|
||||
private workflowAdapter(cloud: CloudProvider) {
|
||||
const adapter = this.requireAdapter(cloud, 'workflows')
|
||||
if (!('startExecution' in adapter) || !('listExecutions' in adapter) || !('describeExecution' in adapter) || !('getExecutionHistory' in adapter) || !('stopExecution' in adapter)) {
|
||||
@@ -860,6 +921,30 @@ export class CloudProxyService {
|
||||
return adapter as import('../adapter-aws/AwsStepFunctionsAdapter').AwsStepFunctionsAdapter
|
||||
}
|
||||
|
||||
private codeBuildAdapter(cloud: CloudProvider) {
|
||||
const adapter = this.requireAdapter(cloud, 'codebuild')
|
||||
if (!adapter.startBuild || !adapter.listBuilds || !adapter.getBuild) {
|
||||
throw new NotSupportedError(`CodeBuild builds are not supported for ${cloud}`)
|
||||
}
|
||||
return adapter
|
||||
}
|
||||
|
||||
private codePipelineAdapter(cloud: CloudProvider) {
|
||||
const adapter = this.requireAdapter(cloud, 'codepipeline')
|
||||
if (!adapter.startPipeline || !adapter.listPipelineExecutions || !adapter.getPipelineState) {
|
||||
throw new NotSupportedError(`CodePipeline executions are not supported for ${cloud}`)
|
||||
}
|
||||
return adapter
|
||||
}
|
||||
|
||||
private codeDeployAdapter(cloud: CloudProvider) {
|
||||
const adapter = this.requireAdapter(cloud, 'codedeploy')
|
||||
if (!adapter.startCodeDeployDeployment || !adapter.listCodeDeployDeployments || !adapter.getCodeDeployDeployment || !adapter.stopCodeDeployDeployment) {
|
||||
throw new NotSupportedError(`CodeDeploy deployments are not supported for ${cloud}`)
|
||||
}
|
||||
return adapter
|
||||
}
|
||||
|
||||
private requireAdapter(cloud: CloudProvider, service: CloudServiceType) {
|
||||
const adapter = this.registry.get(cloud, service)
|
||||
if (!adapter) throw new NotSupportedError(`No adapter registered for ${cloud}/${service}`)
|
||||
|
||||
Reference in New Issue
Block a user