mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
* Create the adf-cli command init-aae-env * Remove the test app * Add basic doc for the init-aae-env command
389 lines
15 KiB
JavaScript
389 lines
15 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/*!
|
|
* @license
|
|
* Copyright 2019 Alfresco Software, Ltd.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import { logging } from '@angular-devkit/core';
|
|
/* tslint:disable */
|
|
const alfrescoApi = require('@alfresco/js-api');
|
|
/* tslint:enable */
|
|
import request = require('request');
|
|
import * as fs from 'fs';
|
|
|
|
export interface ConfigArgs {
|
|
username: string;
|
|
password: string;
|
|
host: string;
|
|
oauth: string;
|
|
identityHost: boolean;
|
|
}
|
|
|
|
const ACTIVITI_CLOUD_APPS: any = {
|
|
CANDIDATE_BASE_APP: {
|
|
name: 'candidatebaseapp',
|
|
file_location: 'https://github.com/Alfresco/alfresco-ng2-components/blob/development/e2e/resources/activiti7/candidatebaseapp.zip?raw=true',
|
|
processes: {
|
|
candidateUserProcess: 'candidateUserProcess',
|
|
candidateGroupProcess: 'candidateGroupProcess',
|
|
anotherCandidateGroupProcess: 'anotherCandidateGroupProcess',
|
|
uploadFileProcess: 'uploadFileProcess'
|
|
},
|
|
security: [
|
|
{'role': 'APS_ADMIN', 'groups': [], 'users': ['superadminuser']},
|
|
{'role': 'APS_USER', 'groups': ['hr', 'testgroup'], 'users': ['hruser']
|
|
}]
|
|
},
|
|
SIMPLE_APP: {
|
|
name: 'simpleapp',
|
|
file_location: 'https://github.com/Alfresco/alfresco-ng2-components/blob/development/e2e/resources/activiti7/simpleapp.zip?raw=true',
|
|
processes: {
|
|
processwithvariables: 'processwithvariables',
|
|
simpleProcess: 'simpleprocess',
|
|
dropdownrestprocess: 'dropdownrestprocess'
|
|
},
|
|
forms: {
|
|
tabVisibilityFields: {
|
|
name: 'tabvisibilitywithfields',
|
|
id: 'form-26b01063-4fb0-455f-b3ba-90172e013678'
|
|
},
|
|
tabVisibilityVars: {
|
|
name: 'tabvisibilitywithvars',
|
|
id: 'form-7bf363d2-83c9-4b00-853e-373d0d59963c'
|
|
}
|
|
},
|
|
security: [
|
|
{'role': 'APS_ADMIN', 'groups': [], 'users': ['superadminuser']},
|
|
{'role': 'APS_USER', 'groups': ['hr', 'testgroup'], 'users': ['hruser']
|
|
}]
|
|
},
|
|
SUB_PROCESS_APP: {
|
|
name: 'subprocessapp',
|
|
file_location: 'https://github.com/Alfresco/alfresco-ng2-components/blob/development/e2e/resources/activiti7/subprocessapp.zip?raw=true',
|
|
security: [
|
|
{'role': 'APS_ADMIN', 'groups': [], 'users': ['superadminuser']},
|
|
{'role': 'APS_USER', 'groups': ['hr', 'testgroup'], 'users': ['hruser']
|
|
}]
|
|
}
|
|
};
|
|
|
|
async function getDeployedApplicationsByStatus(args: ConfigArgs, apiService: any, status: string, logger: logging.Logger) {
|
|
const url = `${args.host}/deployment-service/v1/applications`;
|
|
|
|
const pathParams = {}, queryParams = {status: status},
|
|
headerParams = {}, formParams = {}, bodyParam = {},
|
|
contentTypes = ['application/json'], accepts = ['application/json'];
|
|
|
|
let data;
|
|
try {
|
|
data = await apiService.oauth2Auth.callCustomApi(url, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam,
|
|
contentTypes, accepts);
|
|
return data.list.entries;
|
|
} catch (error) {
|
|
logger.error(`Not possible get the applications from deployment-service ${JSON.stringify(error)} `);
|
|
process.exit(1);
|
|
}
|
|
|
|
}
|
|
|
|
function getAlfrescoJsApiInstance(args: ConfigArgs) {
|
|
const config = {
|
|
provider: 'BPM',
|
|
hostBpm: `${args.host}`,
|
|
authType: 'OAUTH',
|
|
oauth2: {
|
|
host: `${args.oauth}`,
|
|
clientId: 'activiti',
|
|
scope: 'openid',
|
|
secret: '',
|
|
implicitFlow: false,
|
|
silentLogin: false,
|
|
redirectUri: '/'
|
|
},
|
|
identityHost: `${args.identityHost}`
|
|
};
|
|
return new alfrescoApi.AlfrescoApiCompatibility(config);
|
|
}
|
|
|
|
async function _login(args: ConfigArgs, alfrescoJsApi: any, logger: logging.Logger) {
|
|
logger.info(`Perform login...`);
|
|
await alfrescoJsApi.login(args.username, args.password);
|
|
return alfrescoJsApi;
|
|
}
|
|
|
|
async function _deployMissingApps(args: ConfigArgs, logger: logging.Logger) {
|
|
const alfrescoJsApi = getAlfrescoJsApiInstance(args);
|
|
await _login(args, alfrescoJsApi, logger);
|
|
const deployedApps = await getDeployedApplicationsByStatus(args, alfrescoJsApi, '', logger);
|
|
const absentApps = findMissingApps(deployedApps);
|
|
|
|
if (absentApps.length > 0) {
|
|
logger.warn(`Missing apps: ${JSON.stringify(absentApps)}`);
|
|
await checkIfAppIsReleased(args, alfrescoJsApi, absentApps, logger);
|
|
} else {
|
|
logger.warn(`All the apps are correctly deployed`);
|
|
}
|
|
}
|
|
|
|
async function getAppProjects(args: ConfigArgs, apiService: any, logger: logging.Logger) {
|
|
const url = `${args.host}/modeling-service/v1/projects?maxItems=200&skipCount=0`;
|
|
|
|
const pathParams = {}, queryParams = {},
|
|
headerParams = {}, formParams = {}, bodyParam = {},
|
|
contentTypes = ['application/json'], accepts = ['application/json'];
|
|
|
|
let data;
|
|
try {
|
|
data = await apiService.oauth2Auth.callCustomApi(url, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam,
|
|
contentTypes, accepts);
|
|
return data.list.entries;
|
|
} catch (error) {
|
|
logger.error(`Not possible get the application from modeling-service ` + error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
async function checkIfAppIsReleased(args: ConfigArgs, apiService: any, absentApps: any [], logger: logging.Logger) {
|
|
const projectList = await getAppProjects(args, apiService, logger);
|
|
let TIME = 5000;
|
|
let noError = true;
|
|
for (let i = 0; i < absentApps.length; i++) {
|
|
noError = true;
|
|
const currentAbsentApp = absentApps[i];
|
|
const app = projectList.find((currentApp: any) => {
|
|
return currentAbsentApp.name === currentApp.entry.name;
|
|
});
|
|
let projectRelease: any;
|
|
if (app === undefined) {
|
|
logger.warn('Missing project: Create the project for ' + currentAbsentApp.name);
|
|
try {
|
|
const uploadedApp = await importProjectApp(args, apiService, currentAbsentApp, logger);
|
|
logger.warn('Project imported ' + currentAbsentApp.name);
|
|
if (uploadedApp) {
|
|
projectRelease = await releaseProject(args, apiService, uploadedApp, logger);
|
|
}
|
|
} catch (error) {
|
|
if (error.status !== 409) {
|
|
logger.info(`Not possible to upload the project ${app.name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.response.text)}`);
|
|
process.exit(1);
|
|
} else {
|
|
logger.error(`Not possible to upload the project because inconsistency CS - Modelling try to delete manually the node`);
|
|
noError = false;
|
|
}
|
|
}
|
|
} else {
|
|
TIME += 5000;
|
|
logger.info('Project ' + app.entry.name + ' found');
|
|
|
|
const projectReleaseList = await getReleaseAppProjectId(args, apiService, app.entry.id, logger);
|
|
|
|
if (projectReleaseList.list.entries.length === 0) {
|
|
logger.warn('Project needs release');
|
|
projectRelease = await releaseProject(args, apiService, app, logger);
|
|
logger.warn(`Project released: ${projectRelease.id}`);
|
|
} else {
|
|
logger.info('Project already has release');
|
|
|
|
// getting the latest project release
|
|
let currentReleaseVersion = -1;
|
|
projectReleaseList.list.entries.forEach((currentRelease: any) => {
|
|
if (currentRelease.entry.version > currentReleaseVersion) {
|
|
currentReleaseVersion = currentRelease.entry.version;
|
|
projectRelease = currentRelease;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
if (noError) {
|
|
await checkDescriptorExist(args, apiService, currentAbsentApp.name, logger);
|
|
await sleep(TIME, logger);
|
|
await deployApp(args, apiService, currentAbsentApp, projectRelease.entry.id, logger);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function deployApp(args: ConfigArgs, apiService: any, appInfo: any, projectReleaseId: string, logger: logging.Logger) {
|
|
logger.warn(`Deploy app ${appInfo.name} with projectReleaseId ${projectReleaseId}`);
|
|
|
|
const url = `${args.host}/deployment-service/v1/applications`;
|
|
|
|
const pathParams = {};
|
|
const bodyParam = {
|
|
'name': appInfo.name,
|
|
'releaseId': projectReleaseId,
|
|
'security': appInfo.security
|
|
};
|
|
|
|
logger.debug(`Deploy with body: ${JSON.stringify(bodyParam)}`);
|
|
|
|
const headerParams = {}, formParams = {}, queryParams = {},
|
|
contentTypes = ['application/json'], accepts = ['application/json'];
|
|
|
|
try {
|
|
return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam,
|
|
contentTypes, accepts);
|
|
} catch (error) {
|
|
logger.error(`Not possible to deploy the project ${appInfo.name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.response.text)}`);
|
|
// await deleteSiteByName(name);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
async function checkDescriptorExist(args: ConfigArgs, apiService: any, name: string, logger: logging.Logger) {
|
|
logger.info(`Check descriptor ${name} exist in the list `);
|
|
const descriptorList: [] = await getDescriptorList(args, apiService, logger);
|
|
descriptorList.forEach( async(descriptor: any) => {
|
|
if (descriptor.entry.name === name) {
|
|
if (descriptor.entry.deployed === false) {
|
|
await deleteDescriptor(args, apiService, descriptor.entry.name, logger);
|
|
}
|
|
}
|
|
});
|
|
return false;
|
|
}
|
|
|
|
async function getDescriptorList(args: ConfigArgs, apiService: any, logger: logging.Logger) {
|
|
const url = `${args.host}/deployment-service/v1/descriptors?page=0&size=50&sort=lastModifiedAt,desc`;
|
|
|
|
const pathParams = {}, queryParams = {},
|
|
headerParams = {}, formParams = {}, bodyParam = {},
|
|
contentTypes = ['application/json'], accepts = ['application/json'];
|
|
|
|
let data;
|
|
try {
|
|
data = await apiService.oauth2Auth.callCustomApi(url, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam,
|
|
contentTypes, accepts);
|
|
return data.list.entries;
|
|
} catch (error) {
|
|
logger.error(`Not possible get the descriptors from deployment-service ${JSON.stringify(error)} `);
|
|
}
|
|
|
|
}
|
|
|
|
async function deleteDescriptor(args: ConfigArgs, apiService: any, name: string, logger: logging.Logger) {
|
|
logger.warn(`Delete the descriptor ${name}`);
|
|
|
|
const url = `${args.host}/deployment-service/v1/descriptors/${name}`;
|
|
|
|
const pathParams = {};
|
|
const bodyParam = {};
|
|
|
|
const headerParams = {}, formParams = {}, queryParams = {},
|
|
contentTypes = ['application/json'], accepts = ['application/json'];
|
|
|
|
try {
|
|
return await apiService.oauth2Auth.callCustomApi(url, 'DELETE', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts);
|
|
} catch (error) {
|
|
logger.error(`Not possible to delete the descriptor ${name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.response.text)}`);
|
|
}
|
|
}
|
|
|
|
async function releaseProject(args: ConfigArgs, apiService: any, app: any, logger: logging.Logger) {
|
|
const url = `${args.host}/modeling-service/v1/projects/${app.entry.id}/releases`;
|
|
|
|
logger.info(`Release ID ${app.entry.id}`);
|
|
const pathParams = {}, queryParams = {},
|
|
headerParams = {}, formParams = {}, bodyParam = {},
|
|
contentTypes = ['application/json'], accepts = ['application/json'];
|
|
|
|
try {
|
|
return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam,
|
|
contentTypes, accepts);
|
|
} catch (error) {
|
|
logger.info(`Not possible to release the project ${app.entry.name} status : $ \n ${JSON.stringify(error.status)} \n ${JSON.stringify(error.response.text)}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
async function getReleaseAppProjectId(args: ConfigArgs, apiService: any, projectId: string, logger: logging.Logger) {
|
|
const url = `${args.host}/modeling-service/v1/projects/${projectId}/releases`;
|
|
|
|
const pathParams = {}, queryParams = {},
|
|
headerParams = {}, formParams = {}, bodyParam = {},
|
|
contentTypes = ['application/json'], accepts = ['application/json'];
|
|
|
|
try {
|
|
return await apiService.oauth2Auth.callCustomApi(url, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam,
|
|
contentTypes, accepts);
|
|
} catch (error) {
|
|
logger.error(`Not possible to get the release of the project ${projectId} ` + JSON.stringify(error));
|
|
process.exit(1);
|
|
}
|
|
|
|
}
|
|
|
|
async function importProjectApp(args: ConfigArgs, apiService: any, app: any, logger: logging.Logger) {
|
|
await getFileFromRemote(app.file_location, app.name, logger);
|
|
|
|
const file = fs.createReadStream(`${app.name}.zip`).on('error', () => {logger.error(`${app.name}.zip does not exist`); });
|
|
|
|
const url = `${args.host}/modeling-service/v1/projects/import`;
|
|
|
|
const pathParams = {}, queryParams = {},
|
|
headerParams = {}, formParams = {'file': file}, bodyParam = {},
|
|
contentTypes = ['multipart/form-data'], accepts = ['application/json'];
|
|
|
|
logger.warn(`import app ${app.file_location}`);
|
|
const result = await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam,
|
|
contentTypes, accepts);
|
|
deleteLocalFile(`${app.name}`, logger);
|
|
return result;
|
|
}
|
|
|
|
function findMissingApps(deployedApps: any []) {
|
|
const absentApps: any [] = [];
|
|
Object.keys(ACTIVITI_CLOUD_APPS).forEach((key) => {
|
|
const isPresent = deployedApps.find((currentApp: any) => {
|
|
return ACTIVITI_CLOUD_APPS[key].name === currentApp.entry.name;
|
|
});
|
|
|
|
if (!isPresent) {
|
|
absentApps.push(ACTIVITI_CLOUD_APPS[key]);
|
|
}
|
|
});
|
|
return absentApps;
|
|
}
|
|
|
|
async function getFileFromRemote(url: string, name: string, logger: logging.Logger) {
|
|
return new Promise((resolve, reject) => {
|
|
request(url)
|
|
.pipe(fs.createWriteStream(`${name}.zip`))
|
|
.on('finish', () => {
|
|
logger.info(`The file is finished downloading.`);
|
|
resolve();
|
|
})
|
|
.on('error', (error: any) => {
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
|
|
async function deleteLocalFile(name: string, logger: logging.Logger) {
|
|
logger.info(`Deleting local file ${name}.zip`);
|
|
fs.unlinkSync(`${name}.zip`);
|
|
}
|
|
|
|
async function sleep(time: number, logger: logging.Logger) {
|
|
logger.info(`Waiting for ${time} sec...`);
|
|
await new Promise(done => setTimeout(done, time));
|
|
logger.info(`Done...`);
|
|
return;
|
|
}
|
|
|
|
export default async function (args: ConfigArgs, logger: logging.Logger) {
|
|
await _deployMissingApps(args, logger);
|
|
}
|