Skip to content

Commit 7df7b15

Browse files
committed
Merge pull request #744 from cheld/expose-external
Redesign of expose service externally
2 parents 86f2658 + 81629bc commit 7df7b15

File tree

4 files changed

+121
-26
lines changed

4 files changed

+121
-26
lines changed

src/app/frontend/deploy/deployfromsettings.html

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,6 @@
112112
</kd-user-help>
113113
</kd-help-section>
114114

115-
<kd-help-section>
116-
<div class="md-block">
117-
<md-checkbox ng-model="ctrl.isExternal" class="md-primary"
118-
ng-model-options="{ debounce: { 'default': 500, 'blur': 0 } }">
119-
Expose service externally
120-
</md-checkbox>
121-
</div>
122-
<kd-user-help>
123-
</kd-user-help>
124-
</kd-help-section>
125-
126115
<!-- advanced options -->
127116
<div ng-show="ctrl.isMoreOptionsEnabled()">
128117
<kd-help-section>

src/app/frontend/deploy/portmappings.html

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,21 @@
1414
limitations under the License.
1515
-->
1616

17+
<md-input-container class="md-block">
18+
<label>Service</label>
19+
<md-select ng-model="ctrl.serviceType" ng-change="ctrl.changeServiceType()">
20+
<md-option ng-repeat="serviceType in ctrl.serviceTypes" ng-value="serviceType">
21+
{{serviceType.label}}
22+
</md-option>
23+
</md-select>
24+
</md-input-container>
1725
<div ng-repeat="portMapping in ctrl.portMappings">
1826
<ng-form name="portMappingForm" layout="row">
1927
<md-input-container flex="50" class="kd-deploy-input-row">
2028
<label>Port</label>
2129
<input ng-model="portMapping.port" ng-change="ctrl.checkPortMapping(portMappingForm, $index)"
22-
type="number" min="1" max="65535" name="port">
23-
<ng-messages for="portMappingForm.port.$error" role="alert" multiple>
30+
type="number" min="1" max="65535" name="port" ng-required="ctrl.isFirst($index)">
31+
<ng-messages for="portMappingForm.port.$error" role="alert" >
2432
<ng-message when="number">Port must be an integer.</ng-message>
2533
<ng-message when="min">Port must greater than 0.</ng-message>
2634
<ng-message when="max">Port must less than 65536.</ng-message>
@@ -32,8 +40,8 @@
3240
<label>Target port</label>
3341
<input ng-model="portMapping.targetPort"
3442
ng-change="ctrl.checkPortMapping(portMappingForm, $index)"
35-
type="number" min="1" max="65535" name="targetPort">
36-
<ng-messages for="portMappingForm.targetPort.$error" role="alert" multiple>
43+
type="number" min="1" max="65535" name="targetPort" ng-required="ctrl.isFirst($index)">
44+
<ng-messages for="portMappingForm.targetPort.$error" role="alert" >
3745
<ng-message when="number">Target port must be an integer.</ng-message>
3846
<ng-message when="min">Target port must greater than 0.</ng-message>
3947
<ng-message when="max">Target port must less than 65536.</ng-message>

src/app/frontend/deploy/portmappings_controller.js

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,25 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
/** @final */
16+
class ServiceType {
17+
constructor(label, external) {
18+
/** @export {string} */
19+
this.label = label;
20+
/** @export {boolean} */
21+
this.external = external;
22+
}
23+
}
24+
25+
/** @type {ServiceType} */
26+
export const NO_SERVICE = new ServiceType('None', false);
27+
28+
/** @type {ServiceType} */
29+
export const INT_SERVICE = new ServiceType('Internal', false);
30+
31+
/** @type {ServiceType} */
32+
export const EXT_SERVICE = new ServiceType('External', true);
33+
1534
/**
1635
* Controller for the port mappings directive.
1736
*
@@ -24,7 +43,7 @@ export default class PortMappingsController {
2443
* Two way data binding from the scope.
2544
* @export {!Array<!backendApi.PortMapping>}
2645
*/
27-
this.portMappings = [this.newEmptyPortMapping_(this.protocols[0])];
46+
this.portMappings = [];
2847

2948
/**
3049
* Initialized from the scope.
@@ -33,10 +52,22 @@ export default class PortMappingsController {
3352
this.protocols;
3453

3554
/**
36-
* Initialized from the scope.
55+
* Binding to outer scope.
3756
* @export {boolean}
3857
*/
3958
this.isExternal;
59+
60+
/**
61+
* Available service types
62+
* @export {!Array<ServiceType>}
63+
*/
64+
this.serviceTypes = [NO_SERVICE, INT_SERVICE, EXT_SERVICE];
65+
66+
/**
67+
* Selected service type. Binding to outer scope.
68+
* @export {ServiceType}
69+
*/
70+
this.serviceType;
4071
}
4172

4273
/**
@@ -126,4 +157,27 @@ export default class PortMappingsController {
126157
* @private
127158
*/
128159
isPortMappingFilledOrEmpty_(portMapping) { return !portMapping.port === !portMapping.targetPort; }
160+
161+
/**
162+
* Change the service type. Port mappings are adjusted and external flag.
163+
* @export
164+
*/
165+
changeServiceType() {
166+
// add or remove port mappings
167+
if (this.serviceType === NO_SERVICE) {
168+
this.portMappings = [];
169+
} else if (this.portMappings.length === 0) {
170+
this.portMappings = [this.newEmptyPortMapping_(this.protocols[0])];
171+
}
172+
173+
// set flag
174+
this.isExternal = this.serviceType.external;
175+
}
176+
177+
/**
178+
* Returns true if the given port mapping is the first in the list.
179+
* @param {number} index
180+
* @export
181+
*/
182+
isFirst(index) { return (index === 0); }
129183
}

src/test/frontend/deploy/portmappings_controller_test.js

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import deployModule from 'deploy/deploy_module';
1616
import PortMappingsController from 'deploy/portmappings_controller';
17+
import * as serviceTypes from 'deploy/portmappings_controller';
1718

1819
describe('PortMappingsController controller', () => {
1920
/** @type {!PortMappingsController} */
@@ -36,37 +37,73 @@ describe('PortMappingsController controller', () => {
3637
});
3738
});
3839

39-
it('should initialize first value', () => {
40-
expect(ctrl.portMappings).toEqual([{port: null, targetPort: null, protocol: 'FOO'}]);
41-
});
40+
it('should be initialized without port mapping line',
41+
() => { expect(ctrl.portMappings.length).toBe(0); });
4242

43-
it('should add new mappings when needed', () => {
44-
expect(ctrl.portMappings.length).toBe(1);
43+
it('should add or remove port mappings, depending on service type', () => {
4544

46-
ctrl.checkPortMapping(undefined, 0);
45+
// select internal service will add an empty port mapping
46+
ctrl.serviceType = serviceTypes.INT_SERVICE;
47+
ctrl.changeServiceType();
4748
expect(ctrl.portMappings.length).toBe(1);
4849

50+
// select no service will remove all port mappings
51+
ctrl.serviceType = serviceTypes.NO_SERVICE;
52+
ctrl.changeServiceType();
53+
expect(ctrl.portMappings.length).toBe(0);
54+
});
55+
56+
it('should add one additional port mapping when ports are filled', () => {
57+
58+
// given is an empty port mapping line
59+
ctrl.serviceType = serviceTypes.INT_SERVICE;
60+
ctrl.changeServiceType();
61+
62+
// when filling
4963
ctrl.portMappings[0].port = 80;
5064
ctrl.portMappings[0].targetPort = 8080;
51-
5265
ctrl.checkPortMapping(undefined, 0);
66+
67+
// then another line is added
5368
expect(ctrl.portMappings.length).toBe(2);
5469
});
5570

56-
it('should determine removability', () => {
71+
it('should not allow removal if no port mapping line would be left over', () => {
72+
73+
// given is one (empty) port mapping line
74+
ctrl.serviceType = serviceTypes.INT_SERVICE;
75+
ctrl.changeServiceType();
76+
77+
// then it cannot be removed
5778
expect(ctrl.isRemovable(0)).toBe(false);
79+
});
80+
81+
it('should allow removal of one line if another is left over ', () => {
82+
83+
// given is a filled and an empty port mapping line
84+
ctrl.serviceType = serviceTypes.INT_SERVICE;
85+
ctrl.changeServiceType();
5886
ctrl.portMappings[0].port = 80;
5987
ctrl.portMappings[0].targetPort = 8080;
6088
ctrl.checkPortMapping(undefined, 0);
89+
90+
// then the first line is removable
6191
expect(ctrl.isRemovable(0)).toBe(true);
6292
});
6393

6494
it('should remove port mappings', () => {
95+
96+
// given is a filled and an empty port mapping line
97+
ctrl.serviceType = serviceTypes.INT_SERVICE;
98+
ctrl.changeServiceType();
6599
ctrl.portMappings[0].port = 80;
66100
ctrl.portMappings[0].targetPort = 8080;
67101
ctrl.checkPortMapping(undefined, 0);
68-
expect(ctrl.portMappings.length).toBe(2);
102+
103+
// when removing the first line
69104
ctrl.remove(0);
105+
106+
// then the empty line is left over
70107
expect(ctrl.portMappings.length).toBe(1);
71108
expect(ctrl.portMappings[0].port).toBeNull();
72109
});
@@ -82,6 +119,8 @@ describe('PortMappingsController controller', () => {
82119
testData.forEach((testData) => {
83120
// given
84121
let [port, targetPort, portValidity, targetPortValidity] = testData;
122+
ctrl.serviceType = serviceTypes.INT_SERVICE;
123+
ctrl.changeServiceType();
85124
ctrl.portMappings[0].port = port;
86125
ctrl.portMappings[0].targetPort = targetPort;
87126

@@ -93,4 +132,9 @@ describe('PortMappingsController controller', () => {
93132
expect(portMappingForm.targetPort.$valid).toEqual(targetPortValidity);
94133
});
95134
});
135+
136+
it('should identify first index', () => {
137+
expect(ctrl.isFirst(0)).toEqual(true);
138+
expect(ctrl.isFirst(1)).toEqual(false);
139+
});
96140
});

0 commit comments

Comments
 (0)