src/tasks/ECRPushImage/TaskOperations.ts (104 lines of code) (raw):

/*! * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT */ import ECR = require('aws-sdk/clients/ecr') import tl = require('azure-pipelines-task-lib/task') import { DockerHandler } from 'lib/dockerUtils' import { constructTaggedImageName, getEcrAuthorizationData, loginToRegistry } from 'lib/ecrUtils' import { parse } from 'url' import { imageNameSource, TaskParameters } from './TaskParameters' export class TaskOperations { private dockerPath = '' public constructor( public readonly ecrClient: ECR, public readonly dockerHandler: DockerHandler, public readonly taskParameters: TaskParameters ) {} public async execute(): Promise<void> { this.dockerPath = await this.dockerHandler.locateDockerExecutable() let sourceImageRef: string if (this.taskParameters.forceDockerNamingConventions) { // The repository name can only contain lowercase letters, numbers, or - and _. this.taskParameters.repositoryName = this.taskParameters.repositoryName .toLowerCase() .replace(/[^a-z0-9-_.]/g, '') } if (this.taskParameters.imageSource === imageNameSource) { sourceImageRef = constructTaggedImageName( this.taskParameters.sourceImageName, this.taskParameters.sourceImageTag ) console.log(tl.loc('PushImageWithName', sourceImageRef)) } else { sourceImageRef = this.taskParameters.sourceImageId console.log(tl.loc('PushImageWithId', this.taskParameters.sourceImageId)) } const authData = await getEcrAuthorizationData(this.ecrClient) if (!authData) { throw new Error(tl.loc('FailureToObtainAuthToken')) } let endpoint = '' let authToken = '' let proxyEndpoint = '' if (authData.proxyEndpoint) { endpoint = `${parse(authData.proxyEndpoint).host}` } if (!endpoint) { throw new Error(tl.loc('NoValidEndpoint', this.taskParameters.repositoryName)) } if (authData.authorizationToken) { authToken = authData.authorizationToken } if (authData.proxyEndpoint) { proxyEndpoint = authData.proxyEndpoint } if (this.taskParameters.autoCreateRepository) { await this.createRepositoryIfNeeded(this.taskParameters.repositoryName) } const targetImageName = constructTaggedImageName( this.taskParameters.repositoryName, this.taskParameters.pushTag ) const targetImageRef = `${endpoint}/${targetImageName}` await this.tagImage(sourceImageRef, targetImageRef) await loginToRegistry(this.dockerHandler, this.dockerPath, authToken, proxyEndpoint) await this.pushImageToECR(targetImageRef) if (this.taskParameters.outputVariable) { console.log(tl.loc('SettingOutputVariable', this.taskParameters.outputVariable, targetImageRef)) tl.setVariable(this.taskParameters.outputVariable, targetImageRef) } if (this.taskParameters.removeDockerImage) { await this.removeDockerImage(sourceImageRef) } console.log(tl.loc('TaskCompleted')) } private async createRepositoryIfNeeded(repository: string): Promise<void> { console.log(tl.loc('TestingForRepository', repository)) try { await this.ecrClient .describeRepositories({ repositoryNames: [repository] }) .promise() } catch (err) { if (err.code === 'RepositoryNotFoundException') { console.log(tl.loc('CreatingRepository')) await this.ecrClient .createRepository({ repositoryName: repository }) .promise() } else { throw new Error(`Error testing for repository existence: ${err}`) } } } private async tagImage(sourceImageRef: string, imageTag: string): Promise<void> { console.log(tl.loc('AddingTag', imageTag, sourceImageRef)) await this.dockerHandler.runDockerCommand(this.dockerPath, 'tag', [sourceImageRef, imageTag]) } private async pushImageToECR(imageRef: string): Promise<void> { console.log(tl.loc('PushingImage', imageRef)) await this.dockerHandler.runDockerCommand(this.dockerPath, 'push', [imageRef]) } private async removeDockerImage(imageRef: string): Promise<void> { console.log(tl.loc('RemovingImage', imageRef)) await this.dockerHandler.runDockerCommand(this.dockerPath, 'rmi', [imageRef], '-f') } }