You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by lm...@apache.org on 2019/11/02 17:34:21 UTC
[knox] branch master updated: KNOX-2068 - Let end-users add a new
service definition from scratch (#173)
This is an automated email from the ASF dual-hosted git repository.
lmccay pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new d99f1e5 KNOX-2068 - Let end-users add a new service definition from scratch (#173)
d99f1e5 is described below
commit d99f1e50e07ce2910efdf8d681b17ad86623115e
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Sat Nov 2 18:34:14 2019 +0100
KNOX-2068 - Let end-users add a new service definition from scratch (#173)
---
gateway-admin-ui/admin-ui/app/app.module.ts | 2 +
.../admin-ui/app/resource/resource.component.html | 6 ++
.../new-service-definition.component.css | 5 ++
.../new-service-definition.component.html | 27 +++++++
.../new-service-definition.component.ts | 82 ++++++++++++++++++++++
.../servicedefinition-detail.component.ts | 17 +++--
.../servicedefinition.service.ts | 23 +++++-
.../assets/new-service-definition-template.xml | 8 +++
gateway-admin-ui/package-lock.json | 19 +++++
gateway-admin-ui/package.json | 1 +
pom.xml | 1 +
11 files changed, 180 insertions(+), 11 deletions(-)
diff --git a/gateway-admin-ui/admin-ui/app/app.module.ts b/gateway-admin-ui/admin-ui/app/app.module.ts
index c33cf20..5af7431 100644
--- a/gateway-admin-ui/admin-ui/app/app.module.ts
+++ b/gateway-admin-ui/admin-ui/app/app.module.ts
@@ -26,6 +26,7 @@ import {AppComponent} from './app.component';
import {TopologyService} from './topology.service';
import {ServiceDefinitionService} from './service-definition/servicedefinition.service';
import {ServiceDefinitionDetailComponent} from './service-definition/servicedefinition-detail.component';
+import {NewServiceDefinitionComponent} from './service-definition/new-service-definition.component';
import {GatewayVersionService} from './gateway-version.service';
import {GatewayVersionComponent} from './gateway-version.component';
import {TopologyComponent} from './topology.component';
@@ -61,6 +62,7 @@ import {ProviderConfigWizardComponent} from './provider-config-wizard/provider-c
TopologyComponent,
TopologyDetailComponent,
ServiceDefinitionDetailComponent,
+ NewServiceDefinitionComponent,
GatewayVersionComponent,
XmlPipe,
JsonPrettyPipe,
diff --git a/gateway-admin-ui/admin-ui/app/resource/resource.component.html b/gateway-admin-ui/admin-ui/app/resource/resource.component.html
index c586ce2..4845e60 100644
--- a/gateway-admin-ui/admin-ui/app/resource/resource.component.html
+++ b/gateway-admin-ui/admin-ui/app/resource/resource.component.html
@@ -18,6 +18,11 @@
(click)="newDescriptorModal.open()"
title="Create New Descriptor"
data-toggle="tooltip"></span>
+ <span class="clickable inline-glyph glyphicon glyphicon-plus-sign btn btn-xs pull-right"
+ *ngIf="resourceType === 'Service Definitions'"
+ (click)="newServiceDefinitionModal.open()"
+ title="Create New Service Definition"
+ data-toggle="tooltip"></span>
</th>
<th *ngIf="resourceType === 'Topologies'">Timestamp</th>
</tr>
@@ -44,5 +49,6 @@
<div>
<app-new-desc-wizard #newDescriptorModal></app-new-desc-wizard>
<app-provider-config-wizard #newProviderConfigModal></app-provider-config-wizard>
+ <app-service-definition-wizard #newServiceDefinitionModal></app-service-definition-wizard>
</div>
</div>
diff --git a/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.css b/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.css
new file mode 100644
index 0000000..0cc494a
--- /dev/null
+++ b/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.css
@@ -0,0 +1,5 @@
+td {
+ border-collapse: collapse;
+ padding: 8px;
+ vertical-align: top;
+}
\ No newline at end of file
diff --git a/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.html b/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.html
new file mode 100644
index 0000000..96b9205
--- /dev/null
+++ b/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.html
@@ -0,0 +1,27 @@
+<bs-modal (onClose)="onClose()" #newServiceDefinitionModal xmlns="http://www.w3.org/1999/html">
+ <bs-modal-header [showDismiss]="true">
+ <label class="modal-title">Create a New Service Definition</label>
+ </bs-modal-header>
+ <bs-modal-body>
+ <div class="panel-body">
+ <div>
+ <span style="text-shadow: infotext; text-align: center;">At a minimum you must modify the service's name and role attributes!</span>
+ </div>
+ <br />
+ <div>
+ <ace-editor
+ [(text)]="serviceDefinitionContent"
+ [mode]="'xml'"
+ [options]="options"
+ [theme]="theme"
+ style="min-height: 430px; width:100%; overflow: auto;">
+ </ace-editor>
+ </div>
+ </div>
+ </bs-modal-body>
+ <bs-modal-footer>
+ <button type="button" class="btn btn-default btn-sm" (click)="newServiceDefinitionModal.dismiss()">Cancel</button>
+ <button type="button" class="btn btn-primary btn-sm" (click)="newServiceDefinitionModal.close()"
+ [disabled]="!validate()">Ok</button>
+ </bs-modal-footer>
+</bs-modal>
diff --git a/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.ts b/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.ts
new file mode 100644
index 0000000..669d302
--- /dev/null
+++ b/gateway-admin-ui/admin-ui/app/service-definition/new-service-definition.component.ts
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 {Component, OnInit, ViewChild} from '@angular/core';
+import {HttpClient} from '@angular/common/http';
+import {BsModalComponent} from 'ng2-bs3-modal';
+import swal from 'sweetalert';
+
+import {ServiceDefinitionService} from './servicedefinition.service';
+import {ResourceTypesService} from '../resourcetypes/resourcetypes.service';
+
+import 'brace/theme/monokai';
+import 'brace/mode/xml';
+
+@Component({
+ selector: 'app-service-definition-wizard',
+ templateUrl: './new-service-definition.component.html',
+ styleUrls: ['./new-service-definition.component.css']
+})
+export class NewServiceDefinitionComponent implements OnInit {
+
+ serviceDefinitionXmlTemplate = 'assets/new-service-definition-template.xml';
+ defaultServiceDefinitionContent: string;
+ serviceDefinitionContent: string;
+ theme: String = 'monokai';
+ options: any = {useWorker: false, printMargin: false};
+
+ @ViewChild('newServiceDefinitionModal')
+ childModal: BsModalComponent;
+
+ constructor(private http: HttpClient,
+ private serviceDefinitionService: ServiceDefinitionService,
+ private resourceTypesService: ResourceTypesService) {
+ }
+
+ ngOnInit() {
+ this.http.get(this.serviceDefinitionXmlTemplate, {responseType: 'text'})
+ .subscribe(data => this.defaultServiceDefinitionContent = data);
+ }
+
+ open(size?: string) {
+ this.reset();
+ this.childModal.open(size ? size : 'lg');
+ }
+
+ reset() {
+ this.serviceDefinitionContent = this.defaultServiceDefinitionContent;
+ }
+
+ onClose() {
+ this.serviceDefinitionService.saveNewServiceDefinition(this.serviceDefinitionContent)
+ .then(response => {
+ swal('Saved successfully!');
+ this.resourceTypesService.selectResourceType('Service Definitions');
+ this.serviceDefinitionService.selectedServiceDefinition(null);
+ });
+ }
+
+ validate(): boolean {
+ if (this.serviceDefinitionContent) {
+ if (this.serviceDefinitionContent.indexOf('your_service_name') >= 0
+ || this.serviceDefinitionContent.indexOf('YOUR_ROLE') >= 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/gateway-admin-ui/admin-ui/app/service-definition/servicedefinition-detail.component.ts b/gateway-admin-ui/admin-ui/app/service-definition/servicedefinition-detail.component.ts
index 02e4461..b370142 100644
--- a/gateway-admin-ui/admin-ui/app/service-definition/servicedefinition-detail.component.ts
+++ b/gateway-admin-ui/admin-ui/app/service-definition/servicedefinition-detail.component.ts
@@ -16,6 +16,8 @@
*/
import {Component, OnInit, ViewChild} from '@angular/core';
import {BsModalComponent} from 'ng2-bs3-modal/ng2-bs3-modal';
+import swal from 'sweetalert';
+
import {ServiceDefinition} from './servicedefinition';
import {ServiceDefinitionService} from './servicedefinition.service';
import {ResourceTypesService} from '../resourcetypes/resourcetypes.service';
@@ -123,22 +125,19 @@ export class ServiceDefinitionDetailComponent implements OnInit {
updateServiceDefinition() {
this.serviceDefinitionService.updateServiceDefinition(this.changedServiceDefinitionContent ? this.changedServiceDefinitionContent
: this.serviceDefinitionContent)
- .then(() => {
- // This refreshes the list of service definitions
+ .then(response => {
+ swal('Updated successfully!');
this.resourceTypesService.selectResourceType('Service Definitions');
+ this.serviceDefinitionService.selectedServiceDefinition(null);
});
}
deleteServiceDefinition() {
this.serviceDefinitionService.deleteServiceDefinition(this.serviceDefinition)
- .then(() => {
- // This refreshes the list of service definitions
+ .then(response => {
+ swal('Deleted successfully!');
this.resourceTypesService.selectResourceType('Service Definitions');
- // This refreshes the service definition content panel to the first one in the list
- this.serviceDefinitionService.getServiceDefinitions()
- .then(serviceDefinitions => {
- this.serviceDefinitionService.selectedServiceDefinition(serviceDefinitions[0]);
- });
+ this.serviceDefinitionService.selectedServiceDefinition(null);
});
}
}
diff --git a/gateway-admin-ui/admin-ui/app/service-definition/servicedefinition.service.ts b/gateway-admin-ui/admin-ui/app/service-definition/servicedefinition.service.ts
index 75e6b6c..cdb29c7 100644
--- a/gateway-admin-ui/admin-ui/app/service-definition/servicedefinition.service.ts
+++ b/gateway-admin-ui/admin-ui/app/service-definition/servicedefinition.service.ts
@@ -17,6 +17,7 @@
import {Injectable} from '@angular/core';
import {HttpClient, HttpErrorResponse, HttpHeaders} from '@angular/common/http';
import {RestURLBuilder} from 'rest-url-builder';
+import swal from 'sweetalert';
import 'rxjs/add/operator/toPromise';
import {Subject} from 'rxjs/Subject';
@@ -73,6 +74,24 @@ export class ServiceDefinitionService {
});
}
+ saveNewServiceDefinition(xml: string): Promise<string> {
+ let xheaders = new HttpHeaders();
+ xheaders = this.addXmlHeaders(xheaders);
+ let serviceDefintionXml = xml.replace('<serviceDefinitions>', '').replace('</serviceDefinitions>', '');
+ return this.http.post(this.serviceDefinitionsBaseUrl, serviceDefintionXml, {headers: xheaders, responseType: 'text'})
+ .toPromise()
+ .then(response => response)
+ .catch((err: HttpErrorResponse) => {
+ console.debug('ServiceDefinitionService --> saveNewServiceDefinition() --> ' + this.serviceDefinitionsBaseUrl
+ + '\n error: ' + err.status + ' ' + err.message);
+ if (err.status === 401) {
+ window.location.assign(document.location.pathname);
+ } else {
+ return this.handleError(err);
+ }
+ });
+ }
+
updateServiceDefinition(xml: string): Promise<string> {
let xheaders = new HttpHeaders();
xheaders = this.addXmlHeaders(xheaders);
@@ -134,8 +153,8 @@ export class ServiceDefinitionService {
return headers.append('X-Requested-With', 'XMLHttpRequest');
}
- private handleError(error: any): Promise<any> {
- console.error('An error occurred', error); // for demo purposes only
+ private handleError(error: HttpErrorResponse): Promise<any> {
+ swal('Oops!', 'Something went wrong!\n' + (error.error ? error.error : error.statusText), 'error');
return Promise.reject(error.message || error);
}
diff --git a/gateway-admin-ui/admin-ui/assets/new-service-definition-template.xml b/gateway-admin-ui/admin-ui/assets/new-service-definition-template.xml
new file mode 100644
index 0000000..2361638
--- /dev/null
+++ b/gateway-admin-ui/admin-ui/assets/new-service-definition-template.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<serviceDefinition>
+ <service name="your_service_name" role="YOUR_ROLE" version="1.0.0">
+ <dispatch classname="org.apache.knox.gateway.dispatch.DefaultDispatch" use-two-way-ssl="false" />
+ <routes />
+ </service>
+ <rules />
+</serviceDefinition>
diff --git a/gateway-admin-ui/package-lock.json b/gateway-admin-ui/package-lock.json
index 584b8a7..1840163 100644
--- a/gateway-admin-ui/package-lock.json
+++ b/gateway-admin-ui/package-lock.json
@@ -2309,6 +2309,11 @@
"event-emitter": "~0.3.5"
}
},
+ "es6-object-assign": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
+ "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw="
+ },
"es6-set": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
@@ -6216,6 +6221,11 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true
},
+ "promise-polyfill": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.1.0.tgz",
+ "integrity": "sha1-36lpQ+qcEh/KTem1hoyznTRy4Fc="
+ },
"proxy-addr": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
@@ -7862,6 +7872,15 @@
"has-flag": "^2.0.0"
}
},
+ "sweetalert": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.2.tgz",
+ "integrity": "sha512-iWx7X4anRBNDa/a+AdTmvAzQtkN1+s4j/JJRWlHpYE8Qimkohs8/XnFcWeYHH2lMA8LRCa5tj2d244If3S/hzA==",
+ "requires": {
+ "es6-object-assign": "^1.1.0",
+ "promise-polyfill": "^6.0.2"
+ }
+ },
"symbol-observable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
diff --git a/gateway-admin-ui/package.json b/gateway-admin-ui/package.json
index ee6309f..bed8a70 100644
--- a/gateway-admin-ui/package.json
+++ b/gateway-admin-ui/package.json
@@ -29,6 +29,7 @@
"popper.js": "^1.14.7",
"rest-url-builder": "^1.0.6",
"rxjs": "^5.5.2",
+ "sweetalert": "^2.1.2",
"ts-helpers": "^1.1.1",
"zone.js": "^0.8.29"
},
diff --git a/pom.xml b/pom.xml
index 18bfa5c..60fa4bd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -407,6 +407,7 @@
<exclude>**/admin-ui/**/*.html</exclude>
<exclude>atlassian-ide-plugin.xml</exclude>
<exclude>**/PULL_REQUEST_TEMPLATE*</exclude>
+ <exclude>**/new-service-definition-template.xml</exclude>
</excludes>
</configuration>
</plugin>