From: Fiete Ostkamp Date: Mon, 9 Mar 2026 14:20:52 +0000 (+0100) Subject: Add workflow execution page X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=0d7e55ba7149be35365dfd94c5b8ac88cfab9685;p=ccsdk%2Fcds.git Add workflow execution page - add new execute page to sidepane - execute page features - execution setup - execution history (not yet working) - live view (not yet working) - fix 'lateinit property workFlowData has not been initialized' error on /workflow-spec endpoint Issue-ID: CCSDK-4184 Change-Id: I6091a023638bf54d9acab592c9d0c94c00c4ceb6 Signed-off-by: Fiete Ostkamp --- diff --git a/.gitignore b/.gitignore index a25b18906..a14f3ce68 100644 --- a/.gitignore +++ b/.gitignore @@ -163,3 +163,4 @@ MacOS # Generated dependency list direct-dependencies.txt .coverage +out-tsc diff --git a/cds-ui/application/pom.xml b/cds-ui/application/pom.xml index 1d3308f55..8eb601598 100644 --- a/cds-ui/application/pom.xml +++ b/cds-ui/application/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.onap.ccsdk.cds cds-ui - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/cds-ui/client/pom.xml b/cds-ui/client/pom.xml index 143258774..befcc45bc 100644 --- a/cds-ui/client/pom.xml +++ b/cds-ui/client/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.onap.ccsdk.cds cds-ui - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/cds-ui/designer-client/pom.xml b/cds-ui/designer-client/pom.xml index 33c00bb91..44392b024 100644 --- a/cds-ui/designer-client/pom.xml +++ b/cds-ui/designer-client/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.onap.ccsdk.cds cds-ui - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/cds-ui/designer-client/src/app/app-routing.module.ts b/cds-ui/designer-client/src/app/app-routing.module.ts index d0a8e2a28..3e937bcb7 100644 --- a/cds-ui/designer-client/src/app/app-routing.module.ts +++ b/cds-ui/designer-client/src/app/app-routing.module.ts @@ -31,6 +31,10 @@ const routes: Routes = [ path: 'resource-dictionary', loadChildren: './modules/feature-modules/resource-dictionary/resource-dictionary.module#ResourceDictionaryModule' }, + { + path: 'execute', + loadChildren: './modules/feature-modules/execution/execution.module#ExecutionModule' + }, // { path: '', component: MainAppComponent }, { path: '', @@ -45,4 +49,3 @@ const routes: Routes = [ }) export class AppRoutingModule { } - diff --git a/cds-ui/designer-client/src/app/common/constants/app-constants.ts b/cds-ui/designer-client/src/app/common/constants/app-constants.ts index 6f64ee1e8..df58b1042 100644 --- a/cds-ui/designer-client/src/app/common/constants/app-constants.ts +++ b/cds-ui/designer-client/src/app/common/constants/app-constants.ts @@ -100,7 +100,9 @@ export const BlueprintURLs = { getMetaDate: '/controllerblueprint/meta-data/', countOfAllBluePrints: '/controllerblueprint/list/count', getMetaDatePageable: '/controllerblueprint/metadata/paged', - getBlueprintByName: '/controllerblueprint/by-name/' + getBlueprintByName: '/controllerblueprint/by-name/', + getWorkflows: '/controllerblueprint/workflows/', + getWorkflowSpec: '/controllerblueprint/workflow-spec' }; export const ResourceDictionaryURLs = { @@ -124,5 +126,9 @@ export const ControllerCatalogURLs = { getDerivedFrom: '/controllercatalog/model-type/by-derivedfrom' }; +export const ExecutionURLs = { + execute: '/controllerblueprint/execute', +}; + export const ActionElementTypeName = 'app.ActionElement'; diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-api.service.ts b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-api.service.ts new file mode 100644 index 000000000..9efbb0553 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-api.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ApiService } from '../../../common/core/services/api.typed.service'; +import { ExecutionURLs, BlueprintURLs } from '../../../common/constants/app-constants'; +import { BluePrintPage } from '../packages/model/BluePrint.model'; + +@Injectable({ + providedIn: 'root', +}) +export class ExecutionApiService { + + constructor(private api: ApiService) { + } + + executeBlueprint(payload: any): Observable { + return this.api.post(ExecutionURLs.execute, payload); + } + + getPagedPackages(pageNumber: number, pageSize: number, sortBy: string): Observable { + const sortType = sortBy.includes('DATE') ? 'DESC' : 'ASC'; + return this.api.get(BlueprintURLs.getPagedBlueprints, { + offset: pageNumber, + limit: pageSize, + sort: sortBy, + sortType, + }); + } + + getBlueprintByNameAndVersion(name: string, version: string): Observable { + return this.api.get(BlueprintURLs.getBlueprintByName + name + '/version/' + version); + } + + getWorkflows(name: string, version: string): Observable { + return this.api.getCustomized(BlueprintURLs.getWorkflows + name + '/' + version); + } + + getWorkflowSpec(name: string, version: string, workflowName: string): Observable { + return this.api.post(BlueprintURLs.getWorkflowSpec, { + blueprintName: name, + version, + workflowName, + }); + } +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.css new file mode 100644 index 000000000..277ff7249 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.css @@ -0,0 +1,11 @@ +.tab-content { + padding: 20px 0; +} + +.nav-tabs .nav-link { + cursor: pointer; +} + +.nav-tabs .nav-link.active { + font-weight: 600; +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.html new file mode 100644 index 000000000..ce4667721 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.html @@ -0,0 +1,64 @@ + + +
+
+
+
+

+ +

+
+
+
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+
+
+
+
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.ts new file mode 100644 index 000000000..d22babc34 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-dashboard/execution-dashboard.component.ts @@ -0,0 +1,34 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-execution-dashboard', + templateUrl: './execution-dashboard.component.html', + styleUrls: ['./execution-dashboard.component.css'], +}) +export class ExecutionDashboardComponent implements OnInit { + + activeTab = 'setup'; + + // Pre-filled from query params when navigating from package detail + prefilledName = ''; + prefilledVersion = ''; + + constructor(private route: ActivatedRoute) { + } + + ngOnInit() { + this.route.queryParams.subscribe(params => { + if (params.name) { + this.prefilledName = params.name; + } + if (params.version) { + this.prefilledVersion = params.version; + } + }); + } + + selectTab(tab: string) { + this.activeTab = tab; + } +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.css new file mode 100644 index 000000000..7eeb0a95d --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.css @@ -0,0 +1,20 @@ +.execution-history-container { + padding: 15px 0; +} + +.history-row { + cursor: pointer; +} + +.request-id { + font-family: monospace; + font-size: 12px; + max-width: 220px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.empty-state i { + display: block; +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.html new file mode 100644 index 000000000..e1ec19ecf --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.html @@ -0,0 +1,48 @@ +
+
+
+ +
+
+ +
+ +

No execution history yet.

+

Execute a blueprint from the Execution Setup tab to see results here.

+
+ + + + + + + + + + + + + + + + + + + + + + +
Request IDBlueprintVersionActionStatusTimestamp
{{ exec.requestId }}{{ exec.blueprintName }}{{ exec.blueprintVersion }}{{ exec.actionName }} + + {{ exec.status }} + + {{ exec.timestamp }}
+
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.ts new file mode 100644 index 000000000..03b4b3fb9 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-history/execution-history.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit } from '@angular/core'; + +interface ExecutionRecord { + requestId: string; + blueprintName: string; + blueprintVersion: string; + actionName: string; + status: string; + timestamp: string; +} + +@Component({ + selector: 'app-execution-history', + templateUrl: './execution-history.component.html', + styleUrls: ['./execution-history.component.css'], +}) +export class ExecutionHistoryComponent implements OnInit { + + executions: ExecutionRecord[] = []; + selectedExecution: ExecutionRecord = null; + + constructor() { + } + + ngOnInit() { + this.loadHistory(); + } + + loadHistory() { + // History is populated from local session storage for now. + // API-based audit history can be added when the backend enhancement is available. + const raw = sessionStorage.getItem('cds-execution-history'); + if (raw) { + try { + this.executions = JSON.parse(raw); + } catch (_) { + this.executions = []; + } + } + } + + selectExecution(exec: ExecutionRecord) { + this.selectedExecution = exec; + } + + clearHistory() { + this.executions = []; + sessionStorage.removeItem('cds-execution-history'); + this.selectedExecution = null; + } + + get hasHistory(): boolean { + return this.executions.length > 0; + } +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.css new file mode 100644 index 000000000..c0a831e65 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.css @@ -0,0 +1,86 @@ +.execution-setup-container { + padding: 15px 0; +} + +.setup-card, +.editor-card, +.response-card { + border: 1px solid #e0e0e0; + border-radius: 4px; +} + +.setup-card .card-title, +.editor-card .card-title, +.response-card .card-title { + font-size: 14px; + font-weight: 600; + color: #333; + margin-bottom: 15px; +} + +.form-group label { + font-size: 12px; + font-weight: 600; + color: #666; + margin-bottom: 4px; +} + +.btn-execute { + min-width: 120px; +} + +.ace-editor-wrapper { + border: 1px solid #e0e0e0; + border-radius: 3px; +} + +/* Action Inputs */ +.action-inputs-section { + border-top: 1px solid #e0e0e0; + padding-top: 12px; +} + +.section-label { + font-size: 13px; + font-weight: 600; + color: #333; + margin-bottom: 10px; + display: block; +} + +.input-field-label { + font-size: 11px; + font-weight: 600; + color: #555; + margin-bottom: 2px; +} + +.complex-input-group { + margin-bottom: 8px; +} + +.complex-group-label { + font-size: 12px; + font-weight: 600; + color: #444; + margin-bottom: 6px; + display: block; +} + +.complex-fields { + padding-left: 10px; + border-left: 2px solid #e0e0e0; +} + +.complex-fields .form-group { + margin-bottom: 8px; +} + +.input-group-block { + margin-bottom: 4px; +} + +.action-inputs-loading, +.action-inputs-error { + padding: 6px 0; +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.html new file mode 100644 index 000000000..0b6984a74 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.html @@ -0,0 +1,191 @@ +
+
+ +
+
+
+
Blueprint Selection
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + Loading action inputs... +
+ + +
+ + + Could not load input schema. Edit the JSON payload manually. + +
+ + +
+ + +
+ +
+ + + +
+ + +
+ +
+
+ + + +
+
+
+
+
+ +
+ +
+ + +
+
+
+
+ + +
+
+
+
Request Payload (ExecutionServiceInput)
+
+ + +
+
+
+ + +
+
+
+ + + Execution Response +
+
+ + +
+
+
+
+
+
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.ts new file mode 100644 index 000000000..e138f28b3 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution-setup/execution-setup.component.ts @@ -0,0 +1,333 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { ToastrService } from 'ngx-toastr'; +import { ExecutionApiService } from '../execution-api.service'; + +@Component({ + selector: 'app-execution-setup', + templateUrl: './execution-setup.component.html', + styleUrls: ['./execution-setup.component.css'], +}) +export class ExecutionSetupComponent implements OnInit { + + @Input() prefilledName = ''; + @Input() prefilledVersion = ''; + @Output() executionCompleted = new EventEmitter(); + + blueprintName = ''; + blueprintVersion = ''; + actionName = ''; + isExecuting = false; + + availablePackages: any[] = []; + availableVersions: string[] = []; + availableActions: string[] = []; + + // Workflow-spec driven input form + inputGroups: Array<{ + inputName: string; + type: string; + description: string; + required: boolean; + isComplex: boolean; + value: string; + fields: Array<{ + name: string; + type: string; + description: string; + required: boolean; + value: string; + }>; + }> = []; + loadingSpec = false; + specLoadFailed = false; + + payloadText = JSON.stringify(this.defaultPayload(), null, 2); + aceOptions: any = { + maxLines: 30, + minLines: 15, + autoScrollEditorIntoView: true, + showPrintMargin: false, + }; + + lastResponse: any = null; + lastResponseText = ''; + + constructor( + private executionApiService: ExecutionApiService, + private toastService: ToastrService, + ) { + } + + ngOnInit() { + this.loadPackages(); + if (this.prefilledName) { + this.blueprintName = this.prefilledName; + } + if (this.prefilledVersion) { + this.blueprintVersion = this.prefilledVersion; + } + if (this.prefilledName && this.prefilledVersion) { + this.buildPayload(); + } + } + + loadPackages() { + this.executionApiService.getPagedPackages(0, 1000, 'DATE').subscribe( + (pages: any) => { + const page = Array.isArray(pages) ? pages[0] : pages; + const content = page && page.content ? page.content : []; + this.availablePackages = content; + }, + err => { + console.error('Failed to load packages', err); + } + ); + } + + onBlueprintNameChange() { + const matching = this.availablePackages.filter(p => p.artifactName === this.blueprintName); + this.availableVersions = matching.map(p => p.artifactVersion); + if (this.availableVersions.length === 1) { + this.blueprintVersion = this.availableVersions[0]; + } else { + this.blueprintVersion = ''; + } + this.actionName = ''; + this.availableActions = []; + this.inputGroups = []; + this.loadingSpec = false; + this.specLoadFailed = false; + this.buildPayload(); + if (this.blueprintVersion) { + this.loadActions(); + } + } + + onBlueprintVersionChange() { + this.actionName = ''; + this.availableActions = []; + this.inputGroups = []; + this.loadingSpec = false; + this.specLoadFailed = false; + this.buildPayload(); + if (this.blueprintVersion) { + this.loadActions(); + } + } + + loadActions() { + this.executionApiService.getWorkflows(this.blueprintName, this.blueprintVersion).subscribe( + (result: any) => { + if (result && Array.isArray(result.workflows)) { + this.availableActions = result.workflows.slice().sort(); + if (this.availableActions.length === 1) { + this.actionName = this.availableActions[0]; + this.onActionChange(); + } + } + }, + err => { + console.error('Failed to load actions', err); + } + ); + } + + onActionChange() { + if (this.actionName) { + this.loadWorkflowSpec(); + } else { + this.inputGroups = []; + this.specLoadFailed = false; + this.buildPayload(); + } + } + + loadWorkflowSpec() { + this.loadingSpec = true; + this.specLoadFailed = false; + this.inputGroups = []; + this.buildPayload(); + this.executionApiService.getWorkflowSpec( + this.blueprintName, this.blueprintVersion, this.actionName + ).subscribe( + (spec: any) => { + this.loadingSpec = false; + this.resolveWorkflowSpec(spec); + this.buildPayload(); + }, + err => { + this.loadingSpec = false; + this.specLoadFailed = true; + console.error('Failed to load workflow spec', err); + } + ); + } + + resolveWorkflowSpec(spec: any) { + this.inputGroups = []; + if (!spec || !spec.workFlowData || !spec.workFlowData.inputs) { + return; + } + const inputs = spec.workFlowData.inputs; + const dataTypes = spec.dataTypes || {}; + + Object.keys(inputs).forEach(inputName => { + const inputDef = inputs[inputName]; + const typeName = inputDef.type || 'string'; + const dataType = dataTypes[typeName]; + + const group: any = { + inputName, + type: typeName, + description: inputDef.description || '', + required: !!inputDef.required, + isComplex: !!dataType, + value: '', + fields: [], + }; + + if (dataType && dataType.properties) { + group.fields = Object.keys(dataType.properties).map(fieldName => { + const fieldDef = dataType.properties[fieldName]; + return { + name: fieldName, + type: fieldDef.type || 'string', + description: fieldDef.description || '', + required: !!fieldDef.required, + value: '', + }; + }); + } + + this.inputGroups.push(group); + }); + } + + onFieldChange() { + this.buildPayload(); + } + + get uniquePackageNames(): string[] { + const names = new Set(this.availablePackages.map(p => p.artifactName)); + return Array.from(names).sort(); + } + + canExecute(): boolean { + return this.blueprintName.length > 0 + && this.blueprintVersion.length > 0 + && this.payloadText.length > 0 + && !this.isExecuting; + } + + executeBlueprint() { + if (!this.canExecute()) { + return; + } + + let payload: any; + try { + payload = JSON.parse(this.payloadText); + } catch (e) { + this.toastService.error('Invalid JSON payload. Please correct the syntax.'); + return; + } + + this.isExecuting = true; + this.lastResponse = null; + this.lastResponseText = ''; + + this.executionApiService.executeBlueprint(payload).subscribe( + response => { + this.isExecuting = false; + this.lastResponse = response; + this.lastResponseText = JSON.stringify(response, null, 2); + this.toastService.success('Execution completed successfully.'); + this.executionCompleted.emit(response); + }, + error => { + this.isExecuting = false; + const msg = (error.error && error.error.message) || error.message || 'Execution failed'; + this.toastService.error(msg); + this.lastResponseText = JSON.stringify(error.error || error, null, 2); + } + ); + } + + private buildPayload() { + const payload = this.defaultPayload(); + payload.actionIdentifiers.blueprintName = this.blueprintName; + payload.actionIdentifiers.blueprintVersion = this.blueprintVersion; + payload.actionIdentifiers.actionName = this.actionName; + + if (this.actionName) { + const requestKey = this.actionName + '-request'; + const requestObj: any = {}; + + this.inputGroups.forEach(group => { + if (group.isComplex) { + const nested: any = {}; + group.fields.forEach(field => { + nested[field.name] = this.convertValue(field.value, field.type); + }); + requestObj[group.inputName] = nested; + } else { + requestObj[group.inputName] = this.convertValue(group.value, group.type); + } + }); + + payload.payload[requestKey] = requestObj; + } + + this.payloadText = JSON.stringify(payload, null, 2); + } + + private convertValue(value: string, type: string): any { + if (!value) { + return (type === 'integer') ? 0 : (type === 'boolean') ? false : ''; + } + if (type === 'integer') { + const num = parseInt(value, 10); + return isNaN(num) ? 0 : num; + } + if (type === 'boolean') { + return value === 'true'; + } + return value; + } + + resetPayload() { + this.inputGroups.forEach(group => { + group.value = ''; + group.fields.forEach(field => { field.value = ''; }); + }); + this.buildPayload(); + } + + private defaultPayload(): any { + return { + commonHeader: { + originatorId: 'CDS-UI', + requestId: this.generateUUID(), + subRequestId: this.generateUUID(), + timestamp: new Date().toISOString(), + }, + actionIdentifiers: { + blueprintName: '', + blueprintVersion: '', + actionName: '', + mode: 'sync', + }, + payload: {}, + }; + } + + private generateUUID(): string { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + // tslint:disable-next-line:no-bitwise + const r = Math.random() * 16 | 0; + // tslint:disable-next-line:no-bitwise + const v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution.module.ts b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution.module.ts new file mode 100644 index 000000000..8995456d1 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution.module.ts @@ -0,0 +1,30 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { AceEditorModule } from 'ng2-ace-editor'; +import { SharedModulesModule } from '../../shared-modules/shared-modules.module'; +import { ExecutionRoutingModule } from './execution.routing.module'; +import { ExecutionDashboardComponent } from './execution-dashboard/execution-dashboard.component'; +import { ExecutionSetupComponent } from './execution-setup/execution-setup.component'; +import { ExecutionHistoryComponent } from './execution-history/execution-history.component'; +import { LiveViewComponent } from './live-view/live-view.component'; +import { ApiService } from '../../../common/core/services/api.typed.service'; + +@NgModule({ + declarations: [ + ExecutionDashboardComponent, + ExecutionSetupComponent, + ExecutionHistoryComponent, + LiveViewComponent, + ], + imports: [ + CommonModule, + FormsModule, + AceEditorModule, + SharedModulesModule, + ExecutionRoutingModule, + ], + providers: [ApiService], +}) +export class ExecutionModule { +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution.routing.module.ts b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution.routing.module.ts new file mode 100644 index 000000000..b49646fa7 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/execution.routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { ExecutionDashboardComponent } from './execution-dashboard/execution-dashboard.component'; + +const routes: Routes = [ + { + path: '', + component: ExecutionDashboardComponent, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class ExecutionRoutingModule { +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.css b/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.css new file mode 100644 index 000000000..a92f07ebf --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.css @@ -0,0 +1,48 @@ +.live-view-container { + padding: 15px 0; +} + +.status-banner { + padding: 12px 20px; + border-radius: 4px; + font-size: 16px; + font-weight: 600; +} + +.status-success { + background-color: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.status-failure { + background-color: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +.status-completed { + background-color: #d1ecf1; + color: #0c5460; + border: 1px solid #bee5eb; +} + +.response-card { + border: 1px solid #e0e0e0; + border-radius: 4px; +} + +.response-card .card-title { + font-size: 14px; + font-weight: 600; + color: #333; +} + +.ace-editor-wrapper { + border: 1px solid #e0e0e0; + border-radius: 3px; +} + +.empty-state i { + display: block; +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.html new file mode 100644 index 000000000..bb4182f91 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.html @@ -0,0 +1,36 @@ +
+
+ +

No execution response available.

+

Execute a blueprint from the Execution Setup tab to see live results here.

+
+ +
+
+ + + + {{ statusLabel }} +
+ +
+
+
Execution Response (ExecutionServiceOutput)
+
+ + +
+
+
+
+
diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.ts new file mode 100644 index 000000000..dcc9e7004 --- /dev/null +++ b/cds-ui/designer-client/src/app/modules/feature-modules/execution/live-view/live-view.component.ts @@ -0,0 +1,50 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-live-view', + templateUrl: './live-view.component.html', + styleUrls: ['./live-view.component.css'], +}) +export class LiveViewComponent implements OnInit { + + lastResponse: any = null; + lastResponseText = ''; + + constructor() { + } + + ngOnInit() { + // Load the last execution response from session storage + const raw = sessionStorage.getItem('cds-last-execution-response'); + if (raw) { + try { + this.lastResponse = JSON.parse(raw); + this.lastResponseText = JSON.stringify(this.lastResponse, null, 2); + } catch (_) { + this.lastResponse = null; + } + } + } + + get status(): string { + if (!this.lastResponse) { + return 'idle'; + } + if (this.lastResponse.status && this.lastResponse.status.code === 200) { + return 'success'; + } + if (this.lastResponse.status && this.lastResponse.status.code >= 400) { + return 'failure'; + } + return 'completed'; + } + + get statusLabel(): string { + switch (this.status) { + case 'success': return 'Execution Successful'; + case 'failure': return 'Execution Failed'; + case 'completed': return 'Execution Completed'; + default: return 'No Execution Data'; + } + } +} diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html index b5581d96b..020da34cc 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html @@ -738,6 +738,10 @@ [title]="isMetadataValid ? 'Deploy package' : 'Fill in all required metadata fields before deploying'"> Deploy + diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts index 4c48f592a..f297e9a64 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts @@ -250,6 +250,15 @@ export class ConfigurationDashboardComponent extends ComponentCanDeactivate impl this.router.navigate(['/packages/designer', id, { actionName: this.customActionName }]); } + goToExecute() { + this.router.navigate(['/execute'], { + queryParams: { + name: this.viewedPackage.artifactName, + version: this.viewedPackage.artifactVersion + } + }); + } + public dropped(files: NgxFileDropEntry[]) { } diff --git a/cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html b/cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html index c824a6f88..91b6b1d42 100644 --- a/cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html +++ b/cds-ui/designer-client/src/app/modules/shared-modules/header/header.component.html @@ -17,6 +17,12 @@ + +
  • + Execute + + +
  • - \ No newline at end of file + diff --git a/cds-ui/e2e-playwright/mock-processor/fixtures/blueprints.json b/cds-ui/e2e-playwright/mock-processor/fixtures/blueprints.json index 2b33f04fd..8dcc9721c 100644 --- a/cds-ui/e2e-playwright/mock-processor/fixtures/blueprints.json +++ b/cds-ui/e2e-playwright/mock-processor/fixtures/blueprints.json @@ -10,7 +10,12 @@ "artifactName": "RT-resource-resolution", "published": "Y", "updatedBy": "Selffish", - "tags": "test, regression" + "tags": "test, regression", + "workflows": { + "resource-resolution": { "steps": {}, "inputs": {}, "outputs": {} }, + "config-assign": { "steps": {}, "inputs": {}, "outputs": {} }, + "config-deploy": { "steps": {}, "inputs": {}, "outputs": {} } + } }, { "id": "bf26fbf2-4bf5-482e-9cc1-e48e4878aceb", @@ -23,7 +28,11 @@ "artifactName": "vLB_CDS_KOTLIN", "published": "Y", "updatedBy": "PLATANIA, MARCO ", - "tags": "test, vDNS-CDS, SCALE-OUT, MARCO" + "tags": "test, vDNS-CDS, SCALE-OUT, MARCO", + "workflows": { + "resource-resolution": { "steps": {}, "inputs": {}, "outputs": {} }, + "health-check": { "steps": {}, "inputs": {}, "outputs": {} } + } }, { "id": "3bca2b79-020d-4c98-ad19-a425a42c17d8", @@ -36,7 +45,10 @@ "artifactName": "vLB_CDS_RESTCONF", "published": "Y", "updatedBy": "Seaudi, Abdelmuhaimen ", - "tags": "vLB-CDS" + "tags": "vLB-CDS", + "workflows": { + "resource-resolution": { "steps": {}, "inputs": {}, "outputs": {} } + } }, { "id": "8713ea11-fbdd-4a58-ae01-e5ba4ff42a44", @@ -49,7 +61,11 @@ "artifactName": "vLB_CDS", "published": "N", "updatedBy": "Seaudi, Abdelmuhaimen ", - "tags": "vLB_CDS" + "tags": "vLB_CDS", + "workflows": { + "resource-resolution": { "steps": {}, "inputs": {}, "outputs": {} }, + "activate-restconf": { "steps": {}, "inputs": {}, "outputs": {} } + } }, { "id": "d97bc302-0077-4cf7-a494-9d070767fac5", @@ -62,7 +78,11 @@ "artifactName": "5G_Core", "published": "Y", "updatedBy": "Thamlur Raju , Sangeeta Bellara ", - "tags": "Thamlur Raju, Malinconico Aniello Paolo,Vamshi, 5G_Core" + "tags": "Thamlur Raju, Malinconico Aniello Paolo,Vamshi, 5G_Core", + "workflows": { + "resource-resolution": { "steps": {}, "inputs": {}, "outputs": {} }, + "config-assign": { "steps": {}, "inputs": {}, "outputs": {} } + } }, { "id": "a63117f8-2aa0-4b96-b8d2-ddaa9fa3b633", @@ -75,7 +95,10 @@ "artifactName": "vFW-CDS", "published": "Y", "updatedBy": "PLATANIA, MARCO ", - "tags": "vFW-CDS" + "tags": "vFW-CDS", + "workflows": { + "resource-resolution": { "steps": {}, "inputs": {}, "outputs": {} } + } }, { "id": "08dbe39c-f3db-40b7-8e77-c5ef069d4f1b", @@ -88,7 +111,11 @@ "artifactName": "pnf_netconf", "published": "N", "updatedBy": "Aarna Services", - "tags": "pnf_netconf" + "tags": "pnf_netconf", + "workflows": { + "config-assign": { "steps": {}, "inputs": {}, "outputs": {} }, + "config-deploy": { "steps": {}, "inputs": {}, "outputs": {} } + } }, { "id": "7b54c252-74a4-4cfa-b4f6-bdaa25c55ee7", @@ -101,7 +128,10 @@ "artifactName": "APACHE", "published": "Y", "updatedBy": "Lukasz Rajewski ", - "tags": "Lukasz Rajewski, CNF" + "tags": "Lukasz Rajewski, CNF", + "workflows": { + "resource-resolution": { "steps": {}, "inputs": {}, "outputs": {} } + } }, { "id": "9c254141-2083-47f6-980e-5b2f33563862", @@ -114,6 +144,9 @@ "artifactName": "ubuntu20", "published": "N", "updatedBy": "RG, ONES ", - "tags": "ubuntu20" + "tags": "ubuntu20", + "workflows": { + "resource-resolution": { "steps": {}, "inputs": {}, "outputs": {} } + } } -] \ No newline at end of file +] diff --git a/cds-ui/e2e-playwright/mock-processor/fixtures/workflow-specs.json b/cds-ui/e2e-playwright/mock-processor/fixtures/workflow-specs.json new file mode 100644 index 000000000..a7be9bc57 --- /dev/null +++ b/cds-ui/e2e-playwright/mock-processor/fixtures/workflow-specs.json @@ -0,0 +1,133 @@ +{ + "resource-resolution": { + "inputs": { + "resolution-key": { + "type": "string", + "required": false, + "description": "Resolution key for the resource resolution" + }, + "store-result": { + "type": "boolean", + "required": false, + "description": "Whether to store the resolved resources" + }, + "resource-assignment-properties": { + "type": "dt-resource-assignment-properties", + "required": true, + "description": "Dynamic properties for resource assignment" + } + }, + "outputs": { + "meshed-template": { "type": "json", "value": {} } + }, + "dataTypes": { + "dt-resource-assignment-properties": { + "derivedFrom": "tosca.datatypes.Dynamic", + "description": "Dynamic DataType for resource assignment", + "properties": { + "service-instance-id": { "type": "string", "required": true, "description": "Service Instance ID" }, + "vnf-id": { "type": "string", "required": true, "description": "VNF Instance ID" }, + "vf-module-id": { "type": "string", "required": false, "description": "VF Module ID" } + } + } + } + }, + "config-assign": { + "inputs": { + "resolution-key": { + "type": "string", + "required": false, + "description": "Resolution key for config assignment" + }, + "config-assign-properties": { + "type": "dt-config-assign-properties", + "required": true, + "description": "Dynamic properties for config assignment" + } + }, + "outputs": {}, + "dataTypes": { + "dt-config-assign-properties": { + "derivedFrom": "tosca.datatypes.Dynamic", + "description": "Dynamic DataType for config assignment", + "properties": { + "service-instance-id": { "type": "string", "required": true, "description": "Service Instance ID" }, + "vnf-id": { "type": "string", "required": true, "description": "VNF Instance ID" }, + "hostname": { "type": "string", "required": false, "description": "Target hostname" } + } + } + } + }, + "config-deploy": { + "inputs": { + "resolution-key": { + "type": "string", + "required": false, + "description": "Resolution key for config deployment" + }, + "config-deploy-properties": { + "type": "dt-config-deploy-properties", + "required": true, + "description": "Dynamic properties for config deployment" + } + }, + "outputs": {}, + "dataTypes": { + "dt-config-deploy-properties": { + "derivedFrom": "tosca.datatypes.Dynamic", + "description": "Dynamic DataType for config deployment", + "properties": { + "service-instance-id": { "type": "string", "required": true, "description": "Service Instance ID" }, + "vnf-id": { "type": "string", "required": true, "description": "VNF Instance ID" }, + "ip-address": { "type": "string", "required": false, "description": "Device IP address" }, + "hostname": { "type": "string", "required": false, "description": "Device hostname" } + } + } + } + }, + "health-check": { + "inputs": { + "health-check-properties": { + "type": "dt-health-check-properties", + "required": true, + "description": "Health check parameters" + } + }, + "outputs": { + "health-check-result": { "type": "string", "value": "" } + }, + "dataTypes": { + "dt-health-check-properties": { + "derivedFrom": "tosca.datatypes.Dynamic", + "description": "Dynamic DataType for health check", + "properties": { + "service-instance-id": { "type": "string", "required": true, "description": "Service Instance ID" }, + "vnf-id": { "type": "string", "required": true, "description": "VNF Instance ID" }, + "health-check-type": { "type": "string", "required": false, "description": "Type of health check to perform" } + } + } + } + }, + "activate-restconf": { + "inputs": { + "activate-restconf-properties": { + "type": "dt-activate-restconf-properties", + "required": true, + "description": "RESTCONF activation parameters" + } + }, + "outputs": {}, + "dataTypes": { + "dt-activate-restconf-properties": { + "derivedFrom": "tosca.datatypes.Dynamic", + "description": "Dynamic DataType for RESTCONF activation", + "properties": { + "service-instance-id": { "type": "string", "required": true, "description": "Service Instance ID" }, + "vnf-id": { "type": "string", "required": true, "description": "VNF Instance ID" }, + "ip-address": { "type": "string", "required": true, "description": "Device IP address" }, + "port": { "type": "integer", "required": false, "description": "RESTCONF port number" } + } + } + } + } +} diff --git a/cds-ui/e2e-playwright/mock-processor/server.js b/cds-ui/e2e-playwright/mock-processor/server.js index efa9c9ae1..f19e73c12 100644 --- a/cds-ui/e2e-playwright/mock-processor/server.js +++ b/cds-ui/e2e-playwright/mock-processor/server.js @@ -37,6 +37,8 @@ const resourceDictionaries = JSON.parse( fs.readFileSync(path.join(FIXTURES, 'resource-dictionaries.json'), 'utf8')); const modelTypes = JSON.parse( fs.readFileSync(path.join(FIXTURES, 'model-types.json'), 'utf8')); +const workflowSpecs = JSON.parse( + fs.readFileSync(path.join(FIXTURES, 'workflow-specs.json'), 'utf8')); // ── helpers ─────────────────────────────────────────────────────────────────── @@ -168,6 +170,17 @@ const server = http.createServer(async (req, res) => { return bp ? json(res, bp) : json(res, { error: 'not found' }, 404); } + // GET /api/v1/blueprint-model/workflows/blueprint-name/:name/version/:version + if (method === 'GET' && + (m = pathname.match(`^${BASE}/blueprint-model/workflows/blueprint-name/([^/]+)/version/([^/]+)$`))) { + const [, name, version] = m; + const bp = blueprints.find( + b => b.artifactName === decodeURIComponent(name) && b.artifactVersion === decodeURIComponent(version)); + if (!bp) return json(res, { error: 'not found' }, 404); + const workflows = bp.workflows ? Object.keys(bp.workflows) : []; + return json(res, { blueprintName: bp.artifactName, version: bp.artifactVersion, workflows }); + } + // GET /api/v1/blueprint-model/download/by-name/:name/version/:version if (method === 'GET' && (m = pathname.match(`^${BASE}/blueprint-model/download/by-name/([^/]+)/version/([^/]+)$`))) { @@ -320,6 +333,73 @@ const server = http.createServer(async (req, res) => { return json(res, { message: 'deleted', name: m[1] }); } + // ── workflow-spec ────────────────────────────────────────────────────────── + + // POST /api/v1/blueprint-model/workflow-spec + if (method === 'POST' && (pathname === `${BASE}/blueprint-model/workflow-spec` || pathname === `${BASE}/blueprint-model/workflow-spec/`)) { + const raw = await readBody(req); + let body; + try { body = JSON.parse(raw); } catch (_) { return json(res, { error: 'invalid body' }, 400); } + const workflowName = body.workflowName || ''; + const spec = workflowSpecs[workflowName]; + if (!spec) { + return json(res, { + code: 404, + status: 'NOT_FOUND', + message: 'No workflow spec found for ' + workflowName + }, 404); + } + return json(res, { + blueprintName: body.blueprintName || '', + version: body.version || '', + workFlowData: { + workFlowName: workflowName, + inputs: spec.inputs || {}, + outputs: spec.outputs || {} + }, + dataTypes: spec.dataTypes || {} + }); + } + + // ── execution-service ────────────────────────────────────────────────────── + + // POST /api/v1/execution-service/process + if (method === 'POST' && (pathname === `${BASE}/execution-service/process` || pathname === `${BASE}/execution-service/process/`)) { + const raw = await readBody(req); + let input; + try { input = JSON.parse(raw); } catch (_) { input = {}; } + const header = (input.commonHeader || {}); + const actionIds = (input.actionIdentifiers || {}); + const response = { + commonHeader: { + timestamp: new Date().toISOString(), + originatorId: header.originatorId || 'CDS', + requestId: header.requestId || 'mock-request-id', + subRequestId: header.subRequestId || 'mock-sub-request-id', + }, + actionIdentifiers: { + blueprintName: actionIds.blueprintName || '', + blueprintVersion: actionIds.blueprintVersion || '', + actionName: actionIds.actionName || '', + mode: actionIds.mode || 'sync', + }, + status: { + code: 200, + eventType: 'EVENT_COMPONENT_EXECUTED', + timestamp: new Date().toISOString(), + message: 'success', + }, + payload: { + 'resource-resolution-response': { + 'meshed-template': { + json: '{"hostname": "mock-host-01", "ip-address": "10.0.0.1"}', + }, + }, + }, + }; + return json(res, response); + } + // ── fallthrough ─────────────────────────────────────────────────────────────── process.stderr.write(`[mock-processor] 404 – no stub for ${method} ${pathname}\n`); json(res, { error: `no stub for ${method} ${pathname}` }, 404); diff --git a/cds-ui/e2e-playwright/tests/execution.spec.ts b/cds-ui/e2e-playwright/tests/execution.spec.ts new file mode 100644 index 000000000..75bab1503 --- /dev/null +++ b/cds-ui/e2e-playwright/tests/execution.spec.ts @@ -0,0 +1,333 @@ +/* + * execution.spec.ts + * + * End-to-end tests for the Blueprint Execution page. These tests verify: + * 1. Page structure – execution dashboard component renders with tabs. + * 2. Navigation – the Execute link in the sidebar navigates to the page. + * 3. Tab switching – Setup / History / Live View tabs work correctly. + * 4. Execution Setup – form fields render, blueprint dropdown is populated + * from the mock-processor, and the JSON payload editor is visible. + * 5. Action selection – selecting a blueprint+version populates the action + * dropdown from the blueprint's workflows. + * 6. Execution API – submitting the form POSTs to the execution endpoint + * and the mock-processor returns a successful response. + * 7. Package detail integration – the Execute button on the package detail + * page navigates to the execution page with pre-filled parameters. + */ + +import { test, expect } from '@playwright/test'; + +// ── helpers ──────────────────────────────────────────────────────────────────── + +/** Wait for the execution dashboard to be rendered. */ +async function waitForExecutionDashboard(page: import('@playwright/test').Page) { + await expect(page.locator('app-execution-dashboard')).toBeAttached({ timeout: 20_000 }); +} + +/** Wait for the blueprint select dropdown to be populated from mock data. */ +async function waitForBlueprintOptions(page: import('@playwright/test').Page) { + await expect(page.locator('#blueprintName option').nth(1)).toBeAttached({ timeout: 20_000 }); +} + +// ───────────────────────────────────────────────────────────────────────────── +// Page structure +// ───────────────────────────────────────────────────────────────────────────── + +test.describe('Execution Page – structure', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/#/execute'); + await page.waitForLoadState('networkidle'); + }); + + test('execution dashboard component is rendered', async ({ page }) => { + await waitForExecutionDashboard(page); + }); + + test('breadcrumb shows Execute', async ({ page }) => { + await waitForExecutionDashboard(page); + const breadcrumb = page.locator('.breadcrumb-header'); + await expect(breadcrumb).toContainText('Execute'); + }); + + test('shows the Execution Setup tab', async ({ page }) => { + await waitForExecutionDashboard(page); + const tab = page.locator('#execution-nav-tab .nav-link', { hasText: 'Execution Setup' }); + await expect(tab).toBeVisible({ timeout: 10_000 }); + }); + + test('shows the Execution History tab', async ({ page }) => { + await waitForExecutionDashboard(page); + const tab = page.locator('#execution-nav-tab .nav-link', { hasText: 'Execution History' }); + await expect(tab).toBeVisible({ timeout: 10_000 }); + }); + + test('shows the Live View tab', async ({ page }) => { + await waitForExecutionDashboard(page); + const tab = page.locator('#execution-nav-tab .nav-link', { hasText: 'Live View' }); + await expect(tab).toBeVisible({ timeout: 10_000 }); + }); + + test('Execution Setup tab is active by default', async ({ page }) => { + await waitForExecutionDashboard(page); + const tab = page.locator('#execution-nav-tab .nav-link', { hasText: 'Execution Setup' }); + await expect(tab).toHaveClass(/active/, { timeout: 10_000 }); + }); +}); + +// ───────────────────────────────────────────────────────────────────────────── +// Tab switching +// ───────────────────────────────────────────────────────────────────────────── + +test.describe('Execution Page – tab switching', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/#/execute'); + await waitForExecutionDashboard(page); + }); + + test('clicking History tab shows history content', async ({ page }) => { + const historyTab = page.locator('#execution-nav-tab .nav-link', { hasText: 'Execution History' }); + await historyTab.click(); + await expect(historyTab).toHaveClass(/active/); + await expect(page.locator('app-execution-history')).toBeAttached(); + }); + + test('clicking Live View tab shows live view content', async ({ page }) => { + const liveTab = page.locator('#execution-nav-tab .nav-link', { hasText: 'Live View' }); + await liveTab.click(); + await expect(liveTab).toHaveClass(/active/); + await expect(page.locator('app-live-view')).toBeAttached(); + }); + + test('clicking back to Setup tab re-renders setup form', async ({ page }) => { + // Switch away first + const historyTab = page.locator('#execution-nav-tab .nav-link', { hasText: 'Execution History' }); + await historyTab.click(); + await expect(historyTab).toHaveClass(/active/); + + // Switch back + const setupTab = page.locator('#execution-nav-tab .nav-link', { hasText: 'Execution Setup' }); + await setupTab.click(); + await expect(setupTab).toHaveClass(/active/); + await expect(page.locator('app-execution-setup')).toBeAttached(); + }); +}); + +// ───────────────────────────────────────────────────────────────────────────── +// Execution Setup – form elements +// ───────────────────────────────────────────────────────────────────────────── + +test.describe('Execution Page – setup form', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/#/execute'); + await waitForExecutionDashboard(page); + }); + + test('blueprint name dropdown is rendered', async ({ page }) => { + const select = page.locator('#blueprintName'); + await expect(select).toBeVisible({ timeout: 10_000 }); + }); + + test('blueprint version dropdown is rendered', async ({ page }) => { + const select = page.locator('#blueprintVersion'); + await expect(select).toBeVisible({ timeout: 10_000 }); + }); + + test('action name dropdown is rendered', async ({ page }) => { + const select = page.locator('#actionName'); + await expect(select).toBeVisible({ timeout: 10_000 }); + }); + + test('Execute button is rendered and initially disabled', async ({ page }) => { + const btn = page.locator('.btn-execute'); + await expect(btn).toBeVisible({ timeout: 10_000 }); + await expect(btn).toBeDisabled(); + }); + + test('JSON payload editor is rendered', async ({ page }) => { + // ace-editor renders a div with class "ace_editor" + const editor = page.locator('.ace_editor'); + await expect(editor.first()).toBeVisible({ timeout: 15_000 }); + }); + + test('blueprint dropdown is populated from mock API', async ({ page }) => { + await waitForBlueprintOptions(page); + // We expect at least some options from the fixture data + const options = page.locator('#blueprintName option'); + const count = await options.count(); + // First option is the placeholder, rest are blueprint names + expect(count).toBeGreaterThan(1); + }); +}); + +// ───────────────────────────────────────────────────────────────────────────── +// Execution API integration via mock +// ───────────────────────────────────────────────────────────────────────────── + +/** Helper: select first blueprint + wait for version + wait for actions to load. */ +async function selectBlueprintAndVersion(page: import('@playwright/test').Page) { + await page.selectOption('#blueprintName', { index: 1 }); + // Wait for version dropdown to populate and auto-select + await expect(page.locator('#blueprintVersion option').nth(1)).toBeAttached({ timeout: 10_000 }); + const versionOptions = await page.locator('#blueprintVersion option').count(); + if (versionOptions > 1) { + await page.selectOption('#blueprintVersion', { index: 1 }); + } + // Wait for action dropdown to populate from by-name API + await expect(page.locator('#actionName option').nth(1)).toBeAttached({ timeout: 10_000 }); +} + +test.describe('Execution Page – API integration', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/#/execute'); + await waitForExecutionDashboard(page); + await waitForBlueprintOptions(page); + }); + + test('selecting a blueprint populates the action dropdown', async ({ page }) => { + await selectBlueprintAndVersion(page); + const actionOptions = page.locator('#actionName option'); + const count = await actionOptions.count(); + // placeholder + at least one real action + expect(count).toBeGreaterThan(1); + }); + + test('selecting a blueprint enables the Execute button', async ({ page }) => { + await selectBlueprintAndVersion(page); + // Select an action if not auto-selected + const actionOptions = await page.locator('#actionName option').count(); + if (actionOptions > 1) { + await page.selectOption('#actionName', { index: 1 }); + } + await page.waitForTimeout(300); + const btn = page.locator('.btn-execute'); + await expect(btn).toBeEnabled({ timeout: 5_000 }); + }); + + test('executing a blueprint sends request and receives response', async ({ page }) => { + await selectBlueprintAndVersion(page); + // Select an action + const actionOptions = await page.locator('#actionName option').count(); + if (actionOptions > 1) { + await page.selectOption('#actionName', { index: 1 }); + } + await page.waitForTimeout(300); + + // Click execute and wait for the API round-trip + const [apiResponse] = await Promise.all([ + page.waitForResponse( + resp => resp.url().includes('/controllerblueprint/execute') && resp.status() === 200, + { timeout: 15_000 }, + ), + page.locator('.btn-execute').click(), + ]); + + expect(apiResponse.status()).toBe(200); + + // Verify the response JSON contains expected mock data + const body = await apiResponse.json(); + expect(body).toHaveProperty('status'); + expect(body.status.code).toBe(200); + expect(body.status.message).toBe('success'); + }); +}); + +// ───────────────────────────────────────────────────────────────────────────── +// Dynamic action inputs +// ───────────────────────────────────────────────────────────────────────────── + +test.describe('Execution Page – action inputs', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/#/execute'); + await waitForExecutionDashboard(page); + await waitForBlueprintOptions(page); + }); + + test('selecting an action shows action input fields', async ({ page }) => { + await selectBlueprintAndVersion(page); + // Select the first action + await page.selectOption('#actionName', { index: 1 }); + // Wait for the workflow-spec API call to complete and form to render + const inputsSection = page.locator('#actionInputs'); + await expect(inputsSection).toBeAttached({ timeout: 10_000 }); + }); + + test('complex input group renders nested fields', async ({ page }) => { + await selectBlueprintAndVersion(page); + await page.selectOption('#actionName', { index: 1 }); + // Wait for inputs section + await expect(page.locator('#actionInputs')).toBeAttached({ timeout: 10_000 }); + // Complex group should have nested fields inside .complex-fields + const complexFields = page.locator('.complex-fields input, .complex-fields select'); + const count = await complexFields.count(); + expect(count).toBeGreaterThan(0); + }); + + test('typing in a field updates the JSON payload', async ({ page }) => { + await selectBlueprintAndVersion(page); + await page.selectOption('#actionName', { index: 1 }); + await expect(page.locator('#actionInputs')).toBeAttached({ timeout: 10_000 }); + + // Find the first text input in the inputs section and type a value + const firstInput = page.locator('#actionInputs input[type="text"]').first(); + await firstInput.fill('test-value-123'); + + // Wait for payload to update + await page.waitForTimeout(500); + + // Get the ace editor content and verify the typed value appears + const editorContent = await page.locator('.ace_editor .ace_text-layer').first().textContent(); + expect(editorContent).toContain('test-value-123'); + }); + + test('reset clears input field values', async ({ page }) => { + await selectBlueprintAndVersion(page); + await page.selectOption('#actionName', { index: 1 }); + await expect(page.locator('#actionInputs')).toBeAttached({ timeout: 10_000 }); + + // Fill a field + const firstInput = page.locator('#actionInputs input[type="text"]').first(); + await firstInput.fill('will-be-cleared'); + await page.waitForTimeout(300); + + // Click reset + await page.locator('button', { hasText: 'Reset' }).click(); + await page.waitForTimeout(300); + + // Field should be cleared + await expect(firstInput).toHaveValue(''); + }); + + test('payload JSON includes action-request structure', async ({ page }) => { + await selectBlueprintAndVersion(page); + // Select an action + await page.selectOption('#actionName', { index: 1 }); + await expect(page.locator('#actionInputs')).toBeAttached({ timeout: 10_000 }); + await page.waitForTimeout(500); + + // Check that the payload contains a *-request key + const editorContent = await page.locator('.ace_editor .ace_text-layer').first().textContent(); + expect(editorContent).toMatch(/-request/); + }); +}); + +// ───────────────────────────────────────────────────────────────────────────── +// Sidebar navigation +// ───────────────────────────────────────────────────────────────────────────── + +test.describe('Execution Page – navigation', () => { + test('Execute link is visible in the sidebar', async ({ page }) => { + await page.goto('/#/packages'); + await page.waitForLoadState('networkidle'); + const executeLink = page.locator('.menu-dropdown a', { hasText: 'Execute' }); + await expect(executeLink).toBeVisible({ timeout: 10_000 }); + }); + + test('clicking Execute link in sidebar navigates to execute page', async ({ page }) => { + await page.goto('/#/packages'); + await page.waitForLoadState('networkidle'); + const executeLink = page.locator('.menu-dropdown a', { hasText: 'Execute' }); + await executeLink.click(); + await expect(page).toHaveURL(/\/#\/execute/); + await waitForExecutionDashboard(page); + }); +}); diff --git a/cds-ui/pom.xml b/cds-ui/pom.xml index 4cbea0b60..0a665f0ad 100644 --- a/cds-ui/pom.xml +++ b/cds-ui/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.onap.ccsdk.cds cds-aggregator - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/cds-ui/server/pom.xml b/cds-ui/server/pom.xml index 0b6360c23..b5c7e8898 100644 --- a/cds-ui/server/pom.xml +++ b/cds-ui/server/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.onap.ccsdk.cds cds-ui - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/cds-ui/server/src/controllers/blueprint-rest.controller.ts b/cds-ui/server/src/controllers/blueprint-rest.controller.ts index 15c2e4eb6..9260e906f 100644 --- a/cds-ui/server/src/controllers/blueprint-rest.controller.ts +++ b/cds-ui/server/src/controllers/blueprint-rest.controller.ts @@ -322,6 +322,98 @@ export class BlueprintRestController { }); } + @post('/controllerblueprint/execute') + async executeBlueprint( + @requestBody({ + description: 'ExecutionServiceInput JSON payload', + required: true, + content: { + 'application/json': { + schema: { type: 'object' }, + }, + }, + }) + body: object, + @inject(RestBindings.Http.RESPONSE) response: Response, + ): Promise { + const options = { + url: processorApiConfig.http.url + '/execution-service/process', + headers: { + Authorization: processorApiConfig.http.authToken, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }; + return new Promise((resolve, reject) => { + request_lib.post(options) + .on('error', err => { + reject(err); + }) + .pipe(response) + .once('finish', () => { + resolve(response); + }); + }); + } + + @get('/controllerblueprint/workflows/{name}/{version}') + async getWorkflows( + @param.path.string('name') name: string, + @param.path.string('version') version: string, + @inject(RestBindings.Http.RESPONSE) response: Response, + ): Promise { + const options = { + url: processorApiConfig.http.url + '/blueprint-model/workflows/blueprint-name/' + name + '/version/' + version, + headers: { + Authorization: processorApiConfig.http.authToken, + }, + }; + return new Promise((resolve, reject) => { + request_lib.get(options) + .on('error', err => { + reject(err); + }) + .pipe(response) + .once('finish', () => { + resolve(response); + }); + }); + } + + @post('/controllerblueprint/workflow-spec') + async getWorkflowSpec( + @requestBody({ + description: 'WorkFlowSpecRequest JSON payload', + required: true, + content: { + 'application/json': { + schema: { type: 'object' }, + }, + }, + }) + body: object, + @inject(RestBindings.Http.RESPONSE) response: Response, + ): Promise { + const options = { + url: processorApiConfig.http.url + '/blueprint-model/workflow-spec', + headers: { + Authorization: processorApiConfig.http.authToken, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }; + return new Promise((resolve, reject) => { + request_lib.post(options) + .on('error', err => { + reject(err); + }) + .pipe(response) + .once('finish', () => { + resolve(response); + }); + }); + } + @post('/controllerblueprint/deploy-blueprint') async deploy( @requestBody({ diff --git a/components/cba-parent/pom.xml b/components/cba-parent/pom.xml index c0456da0e..07dedf6c0 100644 --- a/components/cba-parent/pom.xml +++ b/components/cba-parent/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-parent - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT ../../ms/blueprintsprocessor/parent diff --git a/components/model-catalog/blueprint-model/archetype-blueprint/pom.xml b/components/model-catalog/blueprint-model/archetype-blueprint/pom.xml index 88efda224..334a1d520 100644 --- a/components/model-catalog/blueprint-model/archetype-blueprint/pom.xml +++ b/components/model-catalog/blueprint-model/archetype-blueprint/pom.xml @@ -20,7 +20,7 @@ org.onap.ccsdk.cds.components.cba archetype-blueprint - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT maven-archetype Components Model Catalog - Blueprints Model - Archetype Blueprints diff --git a/components/model-catalog/blueprint-model/cba-assembly-descriptor/pom.xml b/components/model-catalog/blueprint-model/cba-assembly-descriptor/pom.xml index 941db1d5b..1dd3ccc00 100644 --- a/components/model-catalog/blueprint-model/cba-assembly-descriptor/pom.xml +++ b/components/model-catalog/blueprint-model/cba-assembly-descriptor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.components.cba blueprint-model - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT cba-assembly-descriptor diff --git a/components/model-catalog/blueprint-model/pom.xml b/components/model-catalog/blueprint-model/pom.xml index b1cfcadde..9acf54535 100644 --- a/components/model-catalog/blueprint-model/pom.xml +++ b/components/model-catalog/blueprint-model/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor cba-parent - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT ../../cba-parent diff --git a/components/model-catalog/blueprint-model/test-blueprint-kotlin-parent/pom.xml b/components/model-catalog/blueprint-model/test-blueprint-kotlin-parent/pom.xml index f9ac3af9a..79d36178a 100644 --- a/components/model-catalog/blueprint-model/test-blueprint-kotlin-parent/pom.xml +++ b/components/model-catalog/blueprint-model/test-blueprint-kotlin-parent/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.components.cba blueprint-model - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT test-blueprint-kotlin-parent diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_cli/pom.xml b/components/model-catalog/blueprint-model/test-blueprint/capability_cli/pom.xml index 95fba776a..010df9296 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/capability_cli/pom.xml +++ b/components/model-catalog/blueprint-model/test-blueprint/capability_cli/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.components.cba test-blueprint-model - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT capability_cli diff --git a/components/model-catalog/blueprint-model/test-blueprint/pom.xml b/components/model-catalog/blueprint-model/test-blueprint/pom.xml index 177c63c50..5d564c965 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/pom.xml +++ b/components/model-catalog/blueprint-model/test-blueprint/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.components.cba blueprint-model - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT test-blueprint-model diff --git a/components/model-catalog/blueprint-model/test-blueprint/resource-audit/pom.xml b/components/model-catalog/blueprint-model/test-blueprint/resource-audit/pom.xml index fcd228eff..784fb26bf 100644 --- a/components/model-catalog/blueprint-model/test-blueprint/resource-audit/pom.xml +++ b/components/model-catalog/blueprint-model/test-blueprint/resource-audit/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.components.cba test-blueprint-model - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT resource-audit diff --git a/components/pom.xml b/components/pom.xml index e2b36f5f0..368614c2b 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds cds-aggregator - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/ms/blueprintsprocessor/application/pom.xml b/ms/blueprintsprocessor/application/pom.xml index b6a9549ed..677e06018 100755 --- a/ms/blueprintsprocessor/application/pom.xml +++ b/ms/blueprintsprocessor/application/pom.xml @@ -24,7 +24,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-parent - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT ../parent diff --git a/ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml b/ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml index 20d94c0b2..f67de37cc 100644 --- a/ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/pom.xml b/ms/blueprintsprocessor/functions/blueprint-audit-status/pom.xml index 17274cffd..4aa5a0fe0 100644 --- a/ms/blueprintsprocessor/functions/blueprint-audit-status/pom.xml +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/cli-executor/pom.xml b/ms/blueprintsprocessor/functions/cli-executor/pom.xml index 0c81fb25f..39d2682a3 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/cli-executor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/config-snapshots/pom.xml b/ms/blueprintsprocessor/functions/config-snapshots/pom.xml index dbbc18a1d..a54cc90d7 100644 --- a/ms/blueprintsprocessor/functions/config-snapshots/pom.xml +++ b/ms/blueprintsprocessor/functions/config-snapshots/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/k8s-connection-plugin/pom.xml b/ms/blueprintsprocessor/functions/k8s-connection-plugin/pom.xml index ecdde0e15..9b09592bb 100644 --- a/ms/blueprintsprocessor/functions/k8s-connection-plugin/pom.xml +++ b/ms/blueprintsprocessor/functions/k8s-connection-plugin/pom.xml @@ -23,7 +23,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/message-prioritization/pom.xml b/ms/blueprintsprocessor/functions/message-prioritization/pom.xml index bec39a342..b759acda7 100644 --- a/ms/blueprintsprocessor/functions/message-prioritization/pom.xml +++ b/ms/blueprintsprocessor/functions/message-prioritization/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/netconf-executor/pom.xml b/ms/blueprintsprocessor/functions/netconf-executor/pom.xml index be196a9cc..d516dd89d 100644 --- a/ms/blueprintsprocessor/functions/netconf-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/netconf-executor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/pom.xml b/ms/blueprintsprocessor/functions/pom.xml index 0bae857ad..600426f17 100755 --- a/ms/blueprintsprocessor/functions/pom.xml +++ b/ms/blueprintsprocessor/functions/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-parent - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT ../parent diff --git a/ms/blueprintsprocessor/functions/python-executor/pom.xml b/ms/blueprintsprocessor/functions/python-executor/pom.xml index b37beef53..62c8b8537 100644 --- a/ms/blueprintsprocessor/functions/python-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/python-executor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/resource-resolution/pom.xml b/ms/blueprintsprocessor/functions/resource-resolution/pom.xml index 38bb57037..c5cd42553 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/pom.xml +++ b/ms/blueprintsprocessor/functions/resource-resolution/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/restconf-executor/pom.xml b/ms/blueprintsprocessor/functions/restconf-executor/pom.xml index ebfff02b1..de2eba031 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/restconf-executor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/functions/restful-executor/pom.xml b/ms/blueprintsprocessor/functions/restful-executor/pom.xml index 5d6133786..ecefcc0d5 100644 --- a/ms/blueprintsprocessor/functions/restful-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/restful-executor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-functions - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.functions diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml index c544d2e11..d8a1b5af6 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-blueprints - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml b/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml index b59d73c47..eee8791e9 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-blueprints - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-validation/pom.xml b/ms/blueprintsprocessor/modules/blueprints/blueprint-validation/pom.xml index ee20ccfa6..dce6a130f 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-validation/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-validation/pom.xml @@ -23,7 +23,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-blueprints - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/blueprints/pom.xml b/ms/blueprintsprocessor/modules/blueprints/pom.xml index d12997bbb..bf00c3b1f 100644 --- a/ms/blueprintsprocessor/modules/blueprints/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-modules - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT modules-blueprints diff --git a/ms/blueprintsprocessor/modules/blueprints/resource-dict/pom.xml b/ms/blueprintsprocessor/modules/blueprints/resource-dict/pom.xml index dbe9a2120..85351f694 100644 --- a/ms/blueprintsprocessor/modules/blueprints/resource-dict/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/resource-dict/pom.xml @@ -23,7 +23,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-blueprints - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/db-lib/pom.xml index 820b5f3ce..3a40e4918 100644 --- a/ms/blueprintsprocessor/modules/commons/db-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/db-lib/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-commons - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml index baee1fb51..5815bfd2b 100644 --- a/ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-commons - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/message-lib/pom.xml index c69e9b06c..f24c8384e 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/message-lib/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-commons - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml index f7d6b8c56..b73665ec4 100644 --- a/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-commons - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/commons/pom.xml b/ms/blueprintsprocessor/modules/commons/pom.xml index d5737e20e..db6390660 100755 --- a/ms/blueprintsprocessor/modules/commons/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/pom.xml @@ -24,7 +24,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-modules - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT modules-commons diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/pom.xml b/ms/blueprintsprocessor/modules/commons/processor-core/pom.xml index 0d830eb56..3f727eb89 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/processor-core/pom.xml @@ -23,7 +23,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-commons - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml index 40ce7391d..77f30e937 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml @@ -23,7 +23,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-commons - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml index 6062f00ba..9fe4f6163 100644 --- a/ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-commons - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml index 0b2921e57..e72afa1bf 100644 --- a/ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-inbounds - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml index c8e63df58..cb815c6c7 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-inbounds - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt index da6311d00..f1931aaad 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt @@ -158,6 +158,8 @@ open class BluePrintModelHandler( workFlowData.inputs = workFlow.inputs workFlowData.outputs = workFlow.outputs + wfRes.workFlowData = workFlowData + if (workFlow.inputs != null) { for ((k, v) in workFlow.inputs!!) { addPropertyInfo(k, v, blueprintContext, wfRes) @@ -169,8 +171,6 @@ open class BluePrintModelHandler( addPropertyInfo(k, v, blueprintContext, wfRes) } } - - wfRes.workFlowData = workFlowData return wfRes } diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt index 6d998d0c0..9a24f5fbc 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt @@ -273,6 +273,77 @@ class BlueprintModelControllerTest { .jsonPath("$.content.length()").isEqualTo(0) } + /** + * Regression test for CCSDK-4184: workFlowData must be set on the response object before the + * input/output property loops run, because updatePropertyInfo() accesses + * res.workFlowData.workFlowName. Without the fix, every call raises + * "lateinit property workFlowData has not been initialized". + */ + @Test + fun test07d_getWorkflowSpec_withInputsAndComplexType_returnsWorkFlowDataAndDataTypes() { + // 'resource-assignment' has one input of the complex type dt-resource-assignment-properties + // which triggers both addPropertyInfo → updatePropertyInfo AND addDataType paths. + webTestClient.post() + .uri("/api/v1/blueprint-model/workflow-spec") + .header( + "Authorization", + "Basic " + Base64.getEncoder() + .encodeToString(("ccsdkapps:ccsdkapps").toByteArray(UTF_8)) + ) + .header("Content-Type", "application/json") + .bodyValue( + """{"blueprintName":"baseconfiguration","version":"1.0.0","workflowName":"resource-assignment"}""" + ) + .exchange() + .expectStatus().isOk + .expectBody() + .jsonPath("$.workFlowData").exists() + .jsonPath("$.workFlowData.workFlowName").isEqualTo("resource-assignment") + .jsonPath("$.workFlowData.inputs").exists() + .jsonPath("$.workFlowData.inputs['resource-assignment-properties']").exists() + .jsonPath("$.dataTypes").exists() + .jsonPath("$.dataTypes['dt-resource-assignment-properties']").exists() + } + + @Test + fun test07e_getWorkflowSpec_withNoInputs_returnsEmptyWorkFlowData() { + // 'activate-restconf' has no inputs or outputs — the loops are skipped entirely, + // but workFlowData must still be populated correctly. + webTestClient.post() + .uri("/api/v1/blueprint-model/workflow-spec") + .header( + "Authorization", + "Basic " + Base64.getEncoder() + .encodeToString(("ccsdkapps:ccsdkapps").toByteArray(UTF_8)) + ) + .header("Content-Type", "application/json") + .bodyValue( + """{"blueprintName":"baseconfiguration","version":"1.0.0","workflowName":"activate-restconf"}""" + ) + .exchange() + .expectStatus().isOk + .expectBody() + .jsonPath("$.workFlowData").exists() + .jsonPath("$.workFlowData.workFlowName").isEqualTo("activate-restconf") + } + + @Test + fun test07f_getWorkflowSpec_unknownWorkflow_returns4xx() { + webTestClient.post() + .uri("/api/v1/blueprint-model/workflow-spec") + .header( + "Authorization", + "Basic " + Base64.getEncoder() + .encodeToString(("ccsdkapps:ccsdkapps").toByteArray(UTF_8)) + ) + .header("Content-Type", "application/json") + .bodyValue( + """{"blueprintName":"baseconfiguration","version":"1.0.0","workflowName":"nonexistent-workflow"}""" + ) + .exchange() + .expectStatus().is5xxServerError + } + @Test @Throws(JSONException::class) fun test08_searchBlueprintModels() { diff --git a/ms/blueprintsprocessor/modules/inbounds/health-api-common/pom.xml b/ms/blueprintsprocessor/modules/inbounds/health-api-common/pom.xml index 4784c2cf7..3f2c20afa 100644 --- a/ms/blueprintsprocessor/modules/inbounds/health-api-common/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/health-api-common/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-inbounds - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/inbounds/health-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/health-api/pom.xml index aac271636..0cfe73188 100644 --- a/ms/blueprintsprocessor/modules/inbounds/health-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/health-api/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-inbounds - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/inbounds/pom.xml b/ms/blueprintsprocessor/modules/inbounds/pom.xml index f1f02bb81..9d33898e1 100644 --- a/ms/blueprintsprocessor/modules/inbounds/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-modules - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT modules-inbounds diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml index 07c5204f7..2bf42bdc6 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-inbounds - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml index 8096f06a5..fbfbcb611 100755 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml @@ -24,7 +24,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-inbounds - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/workflow-api/pom.xml index 273e5751e..a32d3a7bb 100644 --- a/ms/blueprintsprocessor/modules/inbounds/workflow-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-inbounds - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/outbounds/pom.xml b/ms/blueprintsprocessor/modules/outbounds/pom.xml index 1839f5a97..794f53ac9 100644 --- a/ms/blueprintsprocessor/modules/outbounds/pom.xml +++ b/ms/blueprintsprocessor/modules/outbounds/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-modules - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT modules-outbounds diff --git a/ms/blueprintsprocessor/modules/pom.xml b/ms/blueprintsprocessor/modules/pom.xml index 1b07437d4..3593d9d52 100644 --- a/ms/blueprintsprocessor/modules/pom.xml +++ b/ms/blueprintsprocessor/modules/pom.xml @@ -23,7 +23,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-parent - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT ../parent diff --git a/ms/blueprintsprocessor/modules/services/execution-service/pom.xml b/ms/blueprintsprocessor/modules/services/execution-service/pom.xml index cd2dfe1e1..e2874ec3a 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/pom.xml +++ b/ms/blueprintsprocessor/modules/services/execution-service/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-services - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/modules/services/pom.xml b/ms/blueprintsprocessor/modules/services/pom.xml index aa8d0c284..be41eea98 100755 --- a/ms/blueprintsprocessor/modules/services/pom.xml +++ b/ms/blueprintsprocessor/modules/services/pom.xml @@ -24,7 +24,7 @@ org.onap.ccsdk.cds.blueprintsprocessor blueprintsprocessor-modules - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT modules-services diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/pom.xml b/ms/blueprintsprocessor/modules/services/workflow-service/pom.xml index 06fe4fb93..7c5606103 100644 --- a/ms/blueprintsprocessor/modules/services/workflow-service/pom.xml +++ b/ms/blueprintsprocessor/modules/services/workflow-service/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds.blueprintsprocessor modules-services - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor.modules diff --git a/ms/blueprintsprocessor/parent/pom.xml b/ms/blueprintsprocessor/parent/pom.xml index 91662c3b2..2f1efd914 100755 --- a/ms/blueprintsprocessor/parent/pom.xml +++ b/ms/blueprintsprocessor/parent/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds blueprintsprocessor - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.blueprintsprocessor diff --git a/ms/blueprintsprocessor/pom.xml b/ms/blueprintsprocessor/pom.xml index 27612d19a..30503a22d 100755 --- a/ms/blueprintsprocessor/pom.xml +++ b/ms/blueprintsprocessor/pom.xml @@ -22,7 +22,7 @@ org.onap.ccsdk.cds cds-ms - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/ms/command-executor/pom.xml b/ms/command-executor/pom.xml index 07d11b302..f6b706f99 100755 --- a/ms/command-executor/pom.xml +++ b/ms/command-executor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds cds-ms - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/ms/error-catalog/application/pom.xml b/ms/error-catalog/application/pom.xml index 4cf66a5c6..f9c576122 100644 --- a/ms/error-catalog/application/pom.xml +++ b/ms/error-catalog/application/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.error.catalog error-catalog - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT error-catalog-application diff --git a/ms/error-catalog/core/pom.xml b/ms/error-catalog/core/pom.xml index c854cd503..3e1a8d997 100644 --- a/ms/error-catalog/core/pom.xml +++ b/ms/error-catalog/core/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.error.catalog error-catalog - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT error-catalog-core diff --git a/ms/error-catalog/pom.xml b/ms/error-catalog/pom.xml index 973c82afa..7dee56697 100644 --- a/ms/error-catalog/pom.xml +++ b/ms/error-catalog/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds cds-ms - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/ms/error-catalog/services/pom.xml b/ms/error-catalog/services/pom.xml index f08650c1f..93a79ac5d 100644 --- a/ms/error-catalog/services/pom.xml +++ b/ms/error-catalog/services/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.error.catalog error-catalog - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT error-catalog-services diff --git a/ms/pom.xml b/ms/pom.xml index e260f3d5b..1e1bda097 100644 --- a/ms/pom.xml +++ b/ms/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds cds-aggregator - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/ms/py-executor/pom.xml b/ms/py-executor/pom.xml index 716ea39cf..673e8b886 100644 --- a/ms/py-executor/pom.xml +++ b/ms/py-executor/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds cds-ms - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT py-executor diff --git a/ms/sdclistener/application/pom.xml b/ms/sdclistener/application/pom.xml index c755bce59..39f2f6f1c 100644 --- a/ms/sdclistener/application/pom.xml +++ b/ms/sdclistener/application/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.sdclistener sdclistener-parent - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT ../parent diff --git a/ms/sdclistener/distribution/pom.xml b/ms/sdclistener/distribution/pom.xml index 1b764c445..288594b34 100755 --- a/ms/sdclistener/distribution/pom.xml +++ b/ms/sdclistener/distribution/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds.sdclistener sdclistener-parent - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT ../parent diff --git a/ms/sdclistener/parent/pom.xml b/ms/sdclistener/parent/pom.xml index 1225bdce9..83475a3a0 100755 --- a/ms/sdclistener/parent/pom.xml +++ b/ms/sdclistener/parent/pom.xml @@ -23,7 +23,7 @@ org.onap.ccsdk.cds sdclistener - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT org.onap.ccsdk.cds.sdclistener diff --git a/ms/sdclistener/pom.xml b/ms/sdclistener/pom.xml index 4d97f16c2..6fee4cec9 100644 --- a/ms/sdclistener/pom.xml +++ b/ms/sdclistener/pom.xml @@ -21,7 +21,7 @@ org.onap.ccsdk.cds cds-ms - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index c5710835b..45ddefdb2 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ limitations under the License. org.onap.ccsdk.cds cds-aggregator - 1.9.1-SNAPSHOT + 1.10.0-SNAPSHOT pom ccsdk-cds diff --git a/version.properties b/version.properties index d49ce7edd..9e6d20db6 100644 --- a/version.properties +++ b/version.properties @@ -5,11 +5,10 @@ release_name=1 -sprint_number=9 -feature_revision=1 +sprint_number=10 +feature_revision=0 base_version=${release_name}.${sprint_number}.${feature_revision} release_version=${base_version} snapshot_version=${base_version}-SNAPSHOT -