Skip to content

Commit ee86531

Browse files
[JavaToolInstallerV1] Added JavaToolInstallerV1 Task - AB#2198814 (#20482)
* [JavaToolInstallerV1] Added JavaToolInstallerV1 Task - AB#2198814 * Fixed azp-tasks-az-blobstorage-provider source URL * Revised Documentation URL * Incremented minor version * retrigger checks
1 parent 22143f9 commit ee86531

File tree

93 files changed

+37973
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+37973
-1
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ Tasks/InvokeRestApiV1/ @microsoft/release-management-task-team @manolerazvan
288288

289289
Tasks/JavaToolInstallerV0/ @microsoft/akvelon-build-task-team
290290

291+
Tasks/JavaToolInstallerV1/ @microsoft/akvelon-build-task-team
292+
291293
Tasks/JenkinsDownloadArtifactsV1/ @microsoft/release-management-task-team @manolerazvan
292294

293295
Tasks/JenkinsQueueJobV2/ @microsoft/akvelon-build-task-team
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
import * as tl from 'azure-pipelines-task-lib/task';
2+
import msRestAzure = require('azure-pipelines-tasks-azure-arm-rest/azure-arm-common');
3+
import Model = require('azure-pipelines-tasks-azure-arm-rest/azureModels');
4+
import armStorage = require('azure-pipelines-tasks-azure-arm-rest/azure-arm-storage');
5+
import BlobService = require('azp-tasks-az-blobstorage-provider/blobservice');
6+
import { AzureEndpoint } from 'azure-pipelines-tasks-azure-arm-rest/azureModels';
7+
import { AzureRMEndpoint } from 'azure-pipelines-tasks-azure-arm-rest/azure-arm-endpoint';
8+
9+
/**
10+
* Class responsible for downloading artifacts from Azure Blob Storage.
11+
*
12+
* @class AzureStorageArtifactDownloader
13+
*
14+
* @property {string} connectedService - The connected service name.
15+
* @property {string} azureStorageAccountName - The name of the Azure Storage account.
16+
* @property {string} [azureResourceGroupName] - The name of the Azure Resource Group (optional).
17+
* @property {string} containerName - The name of the container in Azure Blob Storage.
18+
* @property {string} commonVirtualPath - The common virtual path within the container.
19+
*
20+
* @constructor
21+
* @param {string} connectedService - The connected service name.
22+
* @param {string} azureStorageAccountName - The name of the Azure Storage account.
23+
* @param {string} containerName - The name of the container in Azure Blob Storage.
24+
* @param {string} commonVirtualPath - The common virtual path within the container.
25+
* @param {string} [azureResourceGroupName] - The name of the Azure Resource Group (optional).
26+
*
27+
* @method downloadArtifacts
28+
* @async
29+
* @param {string} downloadToPath - The local path where the artifacts will be downloaded.
30+
* @param {string} fileType - The type of files to download. If not specified, defaults to all files ("**").
31+
* @returns {Promise<void>} A promise that resolves when the download is complete.
32+
* @throws Will throw an error if the requested URL is too long (status code 414) or any other error occurs during the download process.
33+
*
34+
* @method _getStorageAccountDetails
35+
* @async
36+
* @private
37+
* @returns {Promise<StorageAccountInfo>} A promise that resolves to the storage account details.
38+
*
39+
* @method _legacyGetStorageAccount
40+
* @async
41+
* @private
42+
* @param {armStorage.StorageManagementClient} storageArmClient - The Azure Storage Management client.
43+
* @returns {Promise<Model.StorageAccount>} A promise that resolves to the legacy storage account details.
44+
*
45+
* @method _getStorageAccount
46+
* @async
47+
* @private
48+
* @param {armStorage.StorageManagementClient} storageArmClient - The Azure Storage Management client.
49+
* @returns {Promise<Model.StorageAccount>} A promise that resolves to the storage account details.
50+
*
51+
* @method _getStorageAccountWithResourceGroup
52+
* @async
53+
* @private
54+
* @param {armStorage.StorageManagementClient} storageArmClient - The Azure Storage Management client.
55+
* @param {string} resourceGroupName - The name of the Azure Resource Group.
56+
* @param {string} storageAccountName - The name of the Azure Storage account.
57+
* @returns {Promise<Model.StorageAccount | undefined>} A promise that resolves to the storage account details or undefined if not found.
58+
*
59+
* @method _getARMCredentials
60+
* @async
61+
* @private
62+
* @returns {Promise<msRestAzure.ApplicationTokenCredentials>} A promise that resolves to the Azure Resource Manager credentials.
63+
*/
64+
export class AzureStorageArtifactDownloader {
65+
public connectedService: string;
66+
public azureStorageAccountName: string;
67+
public azureResourceGroupName?: string;
68+
public containerName: string;
69+
public commonVirtualPath: string;
70+
71+
constructor(connectedService: string, azureStorageAccountName: string, containerName: string, commonVirtualPath: string, azureResourceGroupName?: string) {
72+
this.connectedService = connectedService;
73+
this.azureStorageAccountName = azureStorageAccountName;
74+
this.azureResourceGroupName = azureResourceGroupName;
75+
this.containerName = containerName;
76+
this.commonVirtualPath = commonVirtualPath;
77+
}
78+
79+
/**
80+
* Downloads artifacts from Azure Blob Storage to the specified local path.
81+
*
82+
* @param downloadToPath - The local path where the artifacts will be downloaded.
83+
* @param fileType - The type of files to download. If not specified, defaults to all files ("**").
84+
* @returns A promise that resolves when the download is complete.
85+
* @throws Will throw an error if the requested URL is too long (status code 414) or any other error occurs during the download process.
86+
*/
87+
public async downloadArtifacts(downloadToPath: string, fileType: string): Promise<void> {
88+
try {
89+
console.log(tl.loc('DownloadFromAzureBlobStorage', this.containerName));
90+
91+
const endpointObject = await this._getAzureRMEndpoint();
92+
const storageAccount: StorageAccountInfo = await this._getStorageAccountDetails();
93+
const blobService = new BlobService.BlobService(storageAccount.name, "", "", true, endpointObject);
94+
await blobService.downloadBlobs(downloadToPath, this.containerName, this.commonVirtualPath, fileType || "**");
95+
96+
} catch (e) {
97+
if (e.statusCode === 414) throw new Error(tl.loc('RequestedUrlTooLong'));
98+
throw e;
99+
}
100+
}
101+
102+
/**
103+
* Retrieves the storage account details for the specified Azure Storage Account.
104+
*
105+
* This method first attempts to get the storage account details using the provided resource group name
106+
* for a faster query. If the resource group name is not provided or the fast query fails, it falls back
107+
* to a legacy query method.
108+
*
109+
* @returns {Promise<StorageAccountInfo>} A promise that resolves to the storage account information.
110+
*
111+
* @throws Will throw an error if the storage account details cannot be retrieved.
112+
*
113+
* @private
114+
*/
115+
private async _getStorageAccountDetails(): Promise<StorageAccountInfo> {
116+
tl.debug("Getting storage account details for " + this.azureStorageAccountName);
117+
118+
const subscriptionId: string = tl.getEndpointDataParameter(this.connectedService, "subscriptionId", false);
119+
const credentials = await this._getARMCredentials();
120+
const storageArmClient = new armStorage.StorageManagementClient(credentials, subscriptionId);
121+
122+
const isUseOldStorageAccountQuery = process.env.AZP_TASK_FF_JAVATOOLINSTALLER_USE_OLD_SA_QUERY
123+
? !!process.env.AZP_TASK_FF_JAVATOOLINSTALLER_USE_OLD_SA_QUERY
124+
: false;
125+
126+
let storageAccount = null;
127+
if (this.azureResourceGroupName) {
128+
tl.debug("Group name is provided. Using fast query to get storage account details.");
129+
storageAccount = await this._getStorageAccountWithResourceGroup(storageArmClient, this.azureResourceGroupName, this.azureStorageAccountName);
130+
}
131+
132+
if (!storageAccount) {
133+
tl.debug("Group name is not provided or fast query failed. Using legacy query to get storage account details.");
134+
storageAccount = isUseOldStorageAccountQuery
135+
? await this._legacyGetStorageAccount(storageArmClient)
136+
: await this._getStorageAccount(storageArmClient);
137+
138+
}
139+
140+
const storageAccountResourceGroupName = armStorage.StorageAccounts.getResourceGroupNameFromUri(storageAccount.id);
141+
tl.debug("Fetched Storage Account Resource Group name: " + storageAccountResourceGroupName);
142+
143+
return <StorageAccountInfo>{
144+
name: this.azureStorageAccountName,
145+
resourceGroupName: storageAccountResourceGroupName
146+
}
147+
}
148+
149+
/**
150+
* Retrieves a storage account from the list of classic and RM accounts.
151+
*
152+
* @param storageArmClient - The storage management client used to list storage accounts.
153+
* @returns A promise that resolves to the storage account matching the specified name.
154+
* @throws An error if the storage account does not exist.
155+
*/
156+
private async _legacyGetStorageAccount(storageArmClient: armStorage.StorageManagementClient): Promise<Model.StorageAccount> {
157+
const storageAccounts = await storageArmClient.storageAccounts.listClassicAndRMAccounts(null);
158+
const index = storageAccounts.findIndex(account => account.name.toLowerCase() == this.azureStorageAccountName.toLowerCase());
159+
if (index < 0) {
160+
throw new Error(tl.loc("StorageAccountDoesNotExist", this.azureStorageAccountName));
161+
}
162+
163+
return storageAccounts[index];
164+
}
165+
166+
/**
167+
* Retrieves the storage account details using the provided StorageManagementClient.
168+
*
169+
* @param storageArmClient - The client used to manage storage accounts.
170+
* @returns A promise that resolves to the storage account details.
171+
* @throws Will throw an error if the storage account does not exist.
172+
*/
173+
private async _getStorageAccount(storageArmClient: armStorage.StorageManagementClient): Promise<Model.StorageAccount> {
174+
const storageAccount = await storageArmClient.storageAccounts.getClassicOrArmAccountByName(this.azureStorageAccountName, null);
175+
176+
if (!storageAccount) {
177+
throw new Error(tl.loc('StorageAccountDoesNotExist', this.azureStorageAccountName));
178+
}
179+
180+
return storageAccount;
181+
}
182+
183+
/**
184+
* Retrieves the storage account details for a given resource group and storage account name.
185+
*
186+
* @param storageArmClient - The Storage Management Client used to interact with Azure Storage resources.
187+
* @param resourceGroupName - The name of the resource group containing the storage account.
188+
* @param storageAccountName - The name of the storage account to retrieve details for.
189+
* @returns A promise that resolves to the storage account details if found, or undefined if not found.
190+
* @throws Will log a warning if the storage account details cannot be retrieved using a fast query.
191+
*/
192+
private async _getStorageAccountWithResourceGroup(storageArmClient: armStorage.StorageManagementClient, resourceGroupName: string, storageAccountName: string): Promise<Model.StorageAccount | undefined> {
193+
let storageAccount = undefined;
194+
195+
try {
196+
storageAccount = await storageArmClient.storageAccounts.getStorageAccountProperties(resourceGroupName, storageAccountName);
197+
} catch (e) {
198+
tl.warning("Failed to get storage account details using fast query.");
199+
}
200+
201+
if (storageAccount) {
202+
tl.debug("Found storage account details using fast query.");
203+
}
204+
205+
return storageAccount;
206+
}
207+
208+
/**
209+
* Retrieves Azure Resource Manager (ARM) credentials.
210+
*
211+
* @returns {Promise<msRestAzure.ApplicationTokenCredentials>} A promise that resolves to the ARM credentials.
212+
* @private
213+
*/
214+
private async _getARMCredentials(): Promise<msRestAzure.ApplicationTokenCredentials> {
215+
const endpoint: AzureEndpoint = await new AzureRMEndpoint(this.connectedService).getEndpoint();
216+
return endpoint.applicationTokenCredentials;
217+
}
218+
219+
/**
220+
* Retrieves the full Azure Resource Manager (ARM) endpoint details.
221+
*
222+
* @returns {Promise<AzureEndpoint>} A promise that resolves to the AzureEndpoint.
223+
* @private
224+
*/
225+
private async _getAzureRMEndpoint(): Promise<AzureEndpoint> {
226+
const endpoint: AzureEndpoint = await new AzureRMEndpoint(this.connectedService).getEndpoint();
227+
return endpoint;
228+
}
229+
}
230+
231+
/**
232+
* Represents the information of an Azure Storage Account.
233+
*
234+
* @interface StorageAccountInfo
235+
* @property {string} name - The name of the storage account.
236+
* @property {string} resourceGroupName - The name of the resource group that the storage account belongs to.
237+
*/
238+
interface StorageAccountInfo {
239+
name: string;
240+
resourceGroupName: string;
241+
}

0 commit comments

Comments
 (0)