@adobe/aio-cli-plugin-api-mesh 3.7.0 → 3.8.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
- package/src/commands/__fixtures__/files/requestParams.json +2 -2
- package/src/commands/__fixtures__/openapi-schema.json +3 -3
- package/src/commands/__fixtures__/requestParams.json +2 -2
- package/src/commands/__fixtures__/sample_fully_qualified_mesh.json +28 -28
- package/src/commands/__fixtures__/sample_mesh_files.json +22 -22
- package/src/commands/__fixtures__/sample_mesh_invalid_file_content.json +13 -13
- package/src/commands/__fixtures__/sample_mesh_invalid_file_name.json +24 -26
- package/src/commands/__fixtures__/sample_mesh_invalid_paths.json +22 -22
- package/src/commands/__fixtures__/sample_mesh_invalid_type.json +24 -26
- package/src/commands/__fixtures__/sample_mesh_mismatching_path.json +28 -28
- package/src/commands/__fixtures__/sample_mesh_outside_workspace_dir.json +22 -22
- package/src/commands/__fixtures__/sample_mesh_path_from_home.json +13 -13
- package/src/commands/__fixtures__/sample_mesh_subdirectory.json +22 -22
- package/src/commands/__fixtures__/sample_mesh_with_files_array.json +28 -28
- package/src/commands/__fixtures__/sample_secrets_mesh.json +1 -1
- package/src/commands/api-mesh/__tests__/log-get-bulk.test.js +253 -0
- package/src/commands/api-mesh/__tests__/log-get.test.js +234 -0
- package/src/commands/api-mesh/__tests__/log-list.test.js +162 -0
- package/src/commands/api-mesh/log-get-bulk.js +243 -0
- package/src/commands/api-mesh/log-get.js +83 -0
- package/src/commands/api-mesh/log-list.js +105 -0
- package/src/lib/devConsole.js +139 -0
- package/src/utils.js +70 -0
package/src/lib/devConsole.js
CHANGED
|
@@ -112,6 +112,45 @@ const describeMesh = async (organizationId, projectId, workspaceId, workspaceNam
|
|
|
112
112
|
}
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
+
/**
|
|
116
|
+
* List Recent Logs
|
|
117
|
+
*
|
|
118
|
+
* @param {*} organizationId
|
|
119
|
+
* @param {*} projectId
|
|
120
|
+
* @param {*} workspaceId
|
|
121
|
+
* @param {*} workspaceName
|
|
122
|
+
* @param {*} meshId
|
|
123
|
+
* @returns
|
|
124
|
+
*/
|
|
125
|
+
const listLogs = async (organizationCode, projectId, workspaceId, meshId, fileName) => {
|
|
126
|
+
const { accessToken, apiKey } = await getDevConsoleConfig();
|
|
127
|
+
const url = `${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/logs/list`;
|
|
128
|
+
const config = {
|
|
129
|
+
method: 'get',
|
|
130
|
+
url: fileName ? url + `?filename=${fileName}` : url,
|
|
131
|
+
headers: {
|
|
132
|
+
'Authorization': `Bearer ${accessToken}`,
|
|
133
|
+
'x-request-id': global.requestId,
|
|
134
|
+
'x-api-key': apiKey,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
logger.info('Initiating GET %s', url);
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const response = await axios(config);
|
|
142
|
+
|
|
143
|
+
logger.info('Response from GET %s', response.status);
|
|
144
|
+
|
|
145
|
+
if (response?.status === 200) {
|
|
146
|
+
return response.data;
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
logger.error(`Error fetching recent logs: ${error}`);
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
115
154
|
const getMesh = async (organizationId, projectId, workspaceId, workspaceName, meshId) => {
|
|
116
155
|
const { baseUrl: devConsoleUrl, accessToken, apiKey } = await getDevConsoleConfig();
|
|
117
156
|
const config = {
|
|
@@ -1015,6 +1054,103 @@ const getPublicEncryptionKey = async organizationCode => {
|
|
|
1015
1054
|
}
|
|
1016
1055
|
};
|
|
1017
1056
|
|
|
1057
|
+
const getPresignedUrls = async (
|
|
1058
|
+
organizationCode,
|
|
1059
|
+
projectId,
|
|
1060
|
+
workspaceId,
|
|
1061
|
+
meshId,
|
|
1062
|
+
startTime,
|
|
1063
|
+
endTime,
|
|
1064
|
+
) => {
|
|
1065
|
+
const { accessToken, apiKey } = await getDevConsoleConfig();
|
|
1066
|
+
const config = {
|
|
1067
|
+
method: 'get',
|
|
1068
|
+
url: `${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/logs?startDateTime=${startTime}&endDateTime=${endTime}`,
|
|
1069
|
+
headers: {
|
|
1070
|
+
'Authorization': `Bearer ${accessToken}`,
|
|
1071
|
+
'x-request-id': global.requestId,
|
|
1072
|
+
'x-api-key': apiKey,
|
|
1073
|
+
},
|
|
1074
|
+
};
|
|
1075
|
+
|
|
1076
|
+
logger.info(
|
|
1077
|
+
'Initiating GET %s',
|
|
1078
|
+
`${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/logs?startDateTime=${startTime}&endDateTime=${endTime}`,
|
|
1079
|
+
);
|
|
1080
|
+
|
|
1081
|
+
try {
|
|
1082
|
+
const response = await axios(config);
|
|
1083
|
+
|
|
1084
|
+
logger.info('Response from GET %s', response.status);
|
|
1085
|
+
|
|
1086
|
+
if (response?.status === 200) {
|
|
1087
|
+
logger.info(`Presigned urls : ${objToString(response, ['data'])}`);
|
|
1088
|
+
const { presignedUrls, totalSize } = response.data;
|
|
1089
|
+
return {
|
|
1090
|
+
presignedUrls,
|
|
1091
|
+
totalSize,
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
} catch (error) {
|
|
1095
|
+
logger.error(`Error fetching presigned urls: ${error}`);
|
|
1096
|
+
return {
|
|
1097
|
+
urls: {},
|
|
1098
|
+
totalsize: 0,
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
const getLogsByRayId = async (organizationCode, projectId, workspaceId, meshId, rayId) => {
|
|
1104
|
+
const { accessToken, apiKey } = await getDevConsoleConfig();
|
|
1105
|
+
const config = {
|
|
1106
|
+
method: 'get',
|
|
1107
|
+
url: `${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/logs/${rayId}`,
|
|
1108
|
+
headers: {
|
|
1109
|
+
'Authorization': `Bearer ${accessToken}`,
|
|
1110
|
+
'x-request-id': global.requestId,
|
|
1111
|
+
'x-api-key': apiKey,
|
|
1112
|
+
},
|
|
1113
|
+
};
|
|
1114
|
+
|
|
1115
|
+
logger.info(
|
|
1116
|
+
'Initiating GET %s',
|
|
1117
|
+
`${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/logs/${rayId}`,
|
|
1118
|
+
);
|
|
1119
|
+
|
|
1120
|
+
try {
|
|
1121
|
+
const response = await axios(config);
|
|
1122
|
+
|
|
1123
|
+
logger.info('Response from GET log %s', response.status);
|
|
1124
|
+
if (response?.status === 200) {
|
|
1125
|
+
logger.info(`Fetched log: ${objToString(response, ['data'])}`);
|
|
1126
|
+
return response.data;
|
|
1127
|
+
} else {
|
|
1128
|
+
let errorMessage = `Unexpected response status: ${response.status}`;
|
|
1129
|
+
logger.error(errorMessage);
|
|
1130
|
+
throw new Error(errorMessage);
|
|
1131
|
+
}
|
|
1132
|
+
} catch (error) {
|
|
1133
|
+
logger.info('Response from GET Logs %s', error.response.status);
|
|
1134
|
+
if (error.response.status === 404) {
|
|
1135
|
+
// The request was made and the server responded with a 404 status code
|
|
1136
|
+
logger.error('Logs not found for the given Ray ID');
|
|
1137
|
+
|
|
1138
|
+
let errorMessage = `LogNotFound`;
|
|
1139
|
+
logger.error(`${errorMessage}. Received ${error.response.status}, expected 200`);
|
|
1140
|
+
throw new Error(errorMessage);
|
|
1141
|
+
} else if (error.response.status === 500) {
|
|
1142
|
+
// Handle 500 Internal Server Error
|
|
1143
|
+
let errorMessage = `ServerError`;
|
|
1144
|
+
logger.error(errorMessage);
|
|
1145
|
+
throw new Error(errorMessage);
|
|
1146
|
+
} else {
|
|
1147
|
+
let errorMessage = `Something went wrong while getting logs. Received ${error.response.status}`;
|
|
1148
|
+
logger.error(errorMessage);
|
|
1149
|
+
throw new Error(errorMessage);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
|
|
1018
1154
|
module.exports = {
|
|
1019
1155
|
getApiKeyCredential,
|
|
1020
1156
|
describeMesh,
|
|
@@ -1023,6 +1159,7 @@ module.exports = {
|
|
|
1023
1159
|
updateMesh,
|
|
1024
1160
|
deleteMesh,
|
|
1025
1161
|
getMeshId,
|
|
1162
|
+
listLogs,
|
|
1026
1163
|
createAPIMeshCredentials,
|
|
1027
1164
|
getListOfCurrentServices,
|
|
1028
1165
|
subscribeCredentialToServices,
|
|
@@ -1032,4 +1169,6 @@ module.exports = {
|
|
|
1032
1169
|
getTenantFeatures,
|
|
1033
1170
|
getMeshDeployments,
|
|
1034
1171
|
getPublicEncryptionKey,
|
|
1172
|
+
getPresignedUrls,
|
|
1173
|
+
getLogsByRayId,
|
|
1035
1174
|
};
|
package/src/utils.js
CHANGED
|
@@ -67,6 +67,25 @@ const selectFlag = Flags.boolean({
|
|
|
67
67
|
default: false,
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
+
const fileNameFlag = Flags.string({
|
|
71
|
+
description: 'Name of CSV file to export the recent logs to',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const startTimeFlag = Flags.string({
|
|
75
|
+
description: 'Start time for the logs in UTC',
|
|
76
|
+
required: true,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const endTimeFlag = Flags.string({
|
|
80
|
+
description: 'End time for the logs in UTC',
|
|
81
|
+
required: true,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const logFilenameFlag = Flags.string({
|
|
85
|
+
description: 'Path to the output file for logs',
|
|
86
|
+
required: true,
|
|
87
|
+
});
|
|
88
|
+
|
|
70
89
|
/**
|
|
71
90
|
* Parse the meshConfig and get the list of (local) files to be imported
|
|
72
91
|
*
|
|
@@ -534,6 +553,52 @@ function reduceConsecutiveBackslashes(str) {
|
|
|
534
553
|
return result;
|
|
535
554
|
}
|
|
536
555
|
|
|
556
|
+
/**
|
|
557
|
+
* Helper function to suggest a corrected format for the user provided input date
|
|
558
|
+
* @param {string} inputDate
|
|
559
|
+
*/
|
|
560
|
+
function suggestCorrectedDateFormat(inputDate) {
|
|
561
|
+
// Remove any non-numeric characters except 'T' and 'Z'
|
|
562
|
+
let correctedDate = inputDate.replace(/[^\dTZ]/g, '');
|
|
563
|
+
|
|
564
|
+
// If "T" is missing, insert it between the date and time
|
|
565
|
+
if (!/T/.test(correctedDate) && correctedDate.length >= 14) {
|
|
566
|
+
correctedDate = correctedDate.slice(0, 8) + 'T' + correctedDate.slice(8);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// Extract date components for validation
|
|
570
|
+
const month = parseInt(correctedDate.slice(4, 6), 10);
|
|
571
|
+
const day = parseInt(correctedDate.slice(6, 8), 10);
|
|
572
|
+
const hour = parseInt(correctedDate.slice(9, 11), 10);
|
|
573
|
+
const minute = parseInt(correctedDate.slice(11, 13), 10);
|
|
574
|
+
const second = parseInt(correctedDate.slice(13, 15), 10);
|
|
575
|
+
|
|
576
|
+
// Check for invalid month, day, hour, minute, second
|
|
577
|
+
const isValidDate =
|
|
578
|
+
month >= 1 &&
|
|
579
|
+
month <= 12 &&
|
|
580
|
+
day >= 1 &&
|
|
581
|
+
day <= 31 && // Note: Can be further validated by month and year
|
|
582
|
+
hour >= 0 &&
|
|
583
|
+
hour <= 23 &&
|
|
584
|
+
minute >= 0 &&
|
|
585
|
+
minute <= 59 &&
|
|
586
|
+
second >= 0 &&
|
|
587
|
+
second <= 59;
|
|
588
|
+
|
|
589
|
+
if (!isValidDate) {
|
|
590
|
+
return null; // Or return an error-specific message for better UX
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// Add missing characters to match the correct format
|
|
594
|
+
correctedDate = correctedDate.replace(
|
|
595
|
+
/(\d{4})(\d{2})(\d{2})T?(\d{2})(\d{2})(\d{2})Z?/,
|
|
596
|
+
'$1-$2-$3T$4:$5:$6Z',
|
|
597
|
+
);
|
|
598
|
+
|
|
599
|
+
return correctedDate;
|
|
600
|
+
}
|
|
601
|
+
|
|
537
602
|
module.exports = {
|
|
538
603
|
ignoreCacheFlag,
|
|
539
604
|
autoConfirmActionFlag,
|
|
@@ -548,7 +613,12 @@ module.exports = {
|
|
|
548
613
|
debugFlag,
|
|
549
614
|
selectFlag,
|
|
550
615
|
secretsFlag,
|
|
616
|
+
fileNameFlag,
|
|
551
617
|
interpolateSecrets,
|
|
552
618
|
validateSecretsFile,
|
|
553
619
|
encryptSecrets,
|
|
620
|
+
startTimeFlag,
|
|
621
|
+
endTimeFlag,
|
|
622
|
+
logFilenameFlag,
|
|
623
|
+
suggestCorrectedDateFormat,
|
|
554
624
|
};
|