adf-cli command init-aae use the user based on the role (#5364)

* Reuse the common deployment and modeling api

* Add files to testing

* Pass parameters

* Travis initaae with correct parameters

* Travis initaae with correct parameters

* Add cli to the smart build
This commit is contained in:
Maurizio Vitale
2020-01-10 17:02:16 +00:00
committed by GitHub
parent 94e02c0552
commit 26677c6789
17 changed files with 698 additions and 187 deletions

View File

@@ -20,3 +20,4 @@ export * from './pages/public-api';
export * from './models/public-api';
export * from './dialog/public-api';
export * from './utils/public-api';
export * from './structure/public-api';

View File

@@ -0,0 +1,42 @@
/*!
* @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 { AlfrescoApi } from '@alfresco/js-api';
import { browser } from 'protractor';
export abstract class Api {
public api: AlfrescoApi;
testConfig = browser.params;
constructor(root: string) {
this.api = this.configureApi(root);
}
private configureApi(root: string): AlfrescoApi {
const config = browser.params.adminapp.apiConfig;
return new AlfrescoApi({
provider: 'BPM',
authType: config.authType,
oauth2: config.oauth2,
hostBpm: config.bpmHost + '/' + root
});
}
abstract setUp(): Promise<Api>;
abstract tearDown();
}

View File

@@ -0,0 +1,58 @@
/*!
* @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 { E2eRequestApiHelper } from './e2e-request-api.helper';
import { Api } from './api';
import { Logger } from '../utils/logger';
import { ResultSetPaging } from '@alfresco/js-api';
export class Application {
requestApiHelper: E2eRequestApiHelper;
endPoint = `/v1/applications/`;
constructor(api: Api) {
this.requestApiHelper = new E2eRequestApiHelper(api);
}
async deploy(model: any): Promise<any> {
await this.requestApiHelper.post(`${this.endPoint}`, { bodyParam: model});
Logger.info(`[Application] Application '${model.name}' was deployed successfully.`);
}
async delete(applicationId: string): Promise<void> {
await this.requestApiHelper.delete(`${this.endPoint}${applicationId}`);
Logger.info(`[Application] Application: '${applicationId}' was deleted successfully.`);
}
async deleteDescriptor(name: string): Promise<void> {
await this.requestApiHelper.delete(`v1/descriptors/${name}`);
Logger.info(`[Descriptor] Descriptor: '${name}' was deleted successfully.`);
}
async getDescriptors(): Promise<ResultSetPaging> {
Logger.info(`[Descriptor] Return descriptors`);
return this.requestApiHelper.get<ResultSetPaging>(`v1/descriptors`, {});
}
async getApplicationsByStatus(status: string): Promise<ResultSetPaging> {
Logger.info(`[Application] Return application by status: ${status}`);
return this.requestApiHelper.get<ResultSetPaging>(this.endPoint, {
queryParams: { status: status }
});
}
}

View File

@@ -0,0 +1,69 @@
/*!
* @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 { Api } from './api';
import { Application } from './application';
import { Logger } from '../utils/logger';
import { browser } from 'protractor';
import { ResultSetPaging } from '@alfresco/js-api';
export class DeploymentAPI extends Api {
public application: Application;
constructor(ROOT: string = 'deployment-service') {
super(ROOT);
}
async setUp(): Promise<DeploymentAPI> {
await this.login();
this.application = new Application(this);
return this;
}
async tearDown(): Promise<void> {
await this.api.logout();
}
private async login(): Promise<void> {
try {
await this.api.login(
browser.params.adminapp.devops,
browser.params.adminapp.devops_password
);
} catch (error) {
Logger.error(error);
}
}
async deploy(releasedProject: any): Promise<void> {
await this.application.deploy(releasedProject);
}
async deleteDescriptor(name: string): Promise<void> {
await this.application.deleteDescriptor(name);
}
async getDescriptors(): Promise<ResultSetPaging> {
const descriptors = await this.application.getDescriptors();
return descriptors;
}
async getApplicationByStatus(status: string): Promise<ResultSetPaging> {
const applications = this.application.getApplicationsByStatus(status);
return applications;
}
}

View File

@@ -0,0 +1,112 @@
/*!
* @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 { Oauth2Auth } from '@alfresco/js-api/src/authentication/oauth2Auth';
export interface E2eRequestApiHelperOptions {
pathParams?: { [key: string]: any };
queryParams?: { [key: string]: any };
headerParams?: { [key: string]: any };
formParams?: { [key: string]: any };
bodyParam?: { [key: string]: any };
contentTypes?: string[];
accepts?: string[];
returnType?: any;
contextRoot?: string;
responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text';
}
function getDefaultOptions(): E2eRequestApiHelperOptions {
return {
pathParams: {},
queryParams: {},
headerParams: {},
formParams: {},
bodyParam: {},
contentTypes: ['application/json'],
accepts: ['application/json'],
returnType: undefined
};
}
export class E2eRequestApiHelper {
api: Oauth2Auth;
constructor(private backend) {
this.api = backend.api.oauth2Auth;
}
private buildUrl(endPoint: string): string {
const trimSlash = (str: string) => str.replace(/^\/|\/$/g, '');
const host = this.backend.api.config.hostBpm;
const path = '/' + trimSlash(endPoint);
return `${host}${path}`;
}
public get<T>(endPoint: string, overriddenOptions?: E2eRequestApiHelperOptions): PromiseLike<T> {
return this.request<T>('GET', endPoint, overriddenOptions);
}
public post<T>(endPoint: string, overriddenOptions?: E2eRequestApiHelperOptions): PromiseLike<T> {
return this.request<T>('POST', endPoint, overriddenOptions);
}
public put<T>(endPoint: string, overriddenOptions?: E2eRequestApiHelperOptions): PromiseLike<T> {
return this.request<T>('PUT', endPoint, overriddenOptions);
}
public delete<T>(endPoint: string, overriddenOptions?: E2eRequestApiHelperOptions): PromiseLike<T> {
return this.request<T>('DELETE', endPoint, overriddenOptions);
}
private request<T>(httpMethod: string, endPoint: string, overriddenOptions?: E2eRequestApiHelperOptions): PromiseLike<T> {
const options = {
...getDefaultOptions(),
...overriddenOptions
};
const {
pathParams,
queryParams,
headerParams,
formParams,
bodyParam,
contentTypes,
accepts,
returnType,
contextRoot,
responseType
} = options;
return this.api.callCustomApi(
this.buildUrl(endPoint),
httpMethod,
pathParams,
queryParams,
headerParams,
formParams,
bodyParam,
contentTypes,
accepts,
returnType,
contextRoot,
responseType
);
}
}

View File

@@ -0,0 +1,78 @@
/*!
* @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 { Api } from './api';
import { Project } from './project';
import { Logger } from '../utils/logger';
import { browser } from 'protractor';
import { NodeEntry, ResultSetPaging } from '@alfresco/js-api';
export class ModelingAPI extends Api {
public project: Project;
constructor(ROOT: string = 'modeling-service') {
super(ROOT);
}
async setUp(): Promise<ModelingAPI> {
await this.login();
this.project = new Project(this);
return this;
}
async tearDown(): Promise<void> {
await this.api.logout();
}
private async login(): Promise<void> {
try {
await this.api.login(
browser.params.adminapp.modeler,
browser.params.adminapp.modeler_password
);
} catch (error) {
Logger.error(error);
}
}
async createProject(): Promise<NodeEntry> {
const project = await this.project.create();
return project;
}
async releaseProject(project: any): Promise<NodeEntry> {
const releasedProject = await this.project.release(project.entry.id);
return releasedProject;
}
async getProjectRelease(projectId: string): Promise<ResultSetPaging> {
const releasedProject = await this.project.getProjectRelease(projectId);
return releasedProject;
}
async importAndReleaseProject(absoluteFilePath: string): Promise<NodeEntry> {
const project = await this.project.import(absoluteFilePath);
const releasedProject = await this.project.release(project.entry.id);
return releasedProject;
}
async getProjects(): Promise<ResultSetPaging> {
const projects = await this.project.searchProjects();
return projects;
}
}

View File

@@ -0,0 +1,132 @@
/*!
* @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 { browser } from 'protractor';
import { ModelingAPI } from './modeling-api';
import { NodeEntry, ResultSetPaging } from '@alfresco/js-api';
import { UtilApi } from './utilapi';
import { E2eRequestApiHelper, E2eRequestApiHelperOptions } from './e2e-request-api.helper';
import * as fs from 'fs';
import { StringUtil } from '../utils/string.util';
import { Logger } from '../utils/logger';
export class Project {
requestApiHelper: E2eRequestApiHelper;
endPoint = '/v1/projects/';
namePrefix: string = browser.params.namePrefix;
constructor(api: ModelingAPI) {
this.requestApiHelper = new E2eRequestApiHelper(api);
}
async create(modelName: string = this.getRandomName()): Promise<NodeEntry> {
const project = await this.requestApiHelper
.post<NodeEntry>(this.endPoint, {bodyParam: { name: modelName }});
Logger.info(
`[Project] Project created with name: ${project.entry.name} and id: ${
project.entry.id
}.`
);
return project;
}
async createAndWaitUntilAvailable(modelName: string = this.getRandomName()): Promise<NodeEntry> {
try {
const project = await this.create(modelName);
await this.retrySearchProject(project.entry.id);
return project;
} catch (error) {
Logger.error(`[Project] Create and wait for project to be available failed!`);
throw error;
}
}
async get(projectId: string): Promise<NodeEntry> {
return this.requestApiHelper.get<NodeEntry>(`/v1/projects/${projectId}`);
}
async delete(projectId: string): Promise<void> {
await this.requestApiHelper.delete(`/v1/projects/${projectId}`);
Logger.info(
`[Project] Project '${projectId}' was deleted successfully.`
);
}
async release(projectId: string): Promise<any> {
try {
const release = await this.requestApiHelper
.post(`/v1/projects/${projectId}/releases`);
Logger.info(`[Project] Project '${projectId}' was released.`);
return release;
} catch (error) {
Logger.error(`[Project] Release project failed!`);
throw error;
}
}
async getProjectRelease(projectId: string): Promise<any> {
try {
return await this.requestApiHelper
.get<ResultSetPaging>(`/v1/projects/${projectId}/releases`);
} catch (error) {
Logger.error(`[Project] Not able to fetch project release!`);
throw error;
}
}
async import(projectFilePath: string): Promise<NodeEntry> {
const fileContent = await fs.createReadStream(projectFilePath);
const requestOptions: E2eRequestApiHelperOptions = {
formParams: { file: fileContent },
contentTypes: ['multipart/form-data']
};
try {
const project = await this.requestApiHelper
.post<NodeEntry>(`/v1/projects/import`, requestOptions);
Logger.info(`[Project] Project imported with name '${project.entry.name}' and id '${project.entry.id}'.`);
return project;
} catch (error) {
Logger.error(`[Project] Import project failed!`);
throw error;
}
}
async searchProjects(): Promise<ResultSetPaging> {
Logger.info(`[Project] Waiting created project to be ready for listing.`);
return this.requestApiHelper.get<ResultSetPaging>(this.endPoint, {
queryParams: { maxItems: 1000 }
});
}
private async retrySearchProject(modelId: string): Promise<{}> {
const predicate = (result: ResultSetPaging) => {
const foundModel = result.list.entries.find(model => {
return model.entry.id === modelId;
});
return !!foundModel;
};
const apiCall = () => this.searchProjects();
return UtilApi.waitForApi(apiCall, predicate);
}
private getRandomName(): string {
return this.namePrefix + StringUtil.generateRandomString(5).toLowerCase();
}
}

View File

@@ -0,0 +1,21 @@
/*!
* @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.
*/
export * from './api';
export * from './utilapi';
export * from './deployment-api';
export * from './modeling-api';

View File

@@ -0,0 +1,44 @@
/*!
* @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.
*/
export type ApiResultPredicate<T> = (result: T) => boolean;
export type ApiCall<T> = () => Promise<T>;
export class UtilApi {
static async waitForApi<T>(apiCall: ApiCall<T>, predicate: ApiResultPredicate<T>) {
const apiCallWithPredicateChecking = async () => {
const apiCallResult = await apiCall();
if (predicate(apiCallResult)) {
return Promise.resolve(apiCallResult);
} else {
return Promise.reject(apiCallResult);
}
};
return UtilApi.retryCall(apiCallWithPredicateChecking);
}
static retryCall(fn: () => Promise<any>, retry: number = 30, delay: number = 1000): Promise<any> {
const pause = (duration: number) => new Promise((res) => setTimeout(res, duration));
const run = (retries: number) => {
return fn().catch((err) => (retries > 1 ? pause(delay).then(() => run(retries - 1)) : Promise.reject(err)));
};
return run(retry);
}
}