Skip to content

Commit 7bf70c7

Browse files
committed
Respect limit ranges on create storage page
Show the min and max storage capacity and validate the entered value. If min and max are the same, show the value as a read-only field.
1 parent 832cec0 commit 7bf70c7

File tree

7 files changed

+183
-46
lines changed

7 files changed

+183
-46
lines changed

app/scripts/directives/oscPersistentVolumeClaim.js

+53-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@
22

33
angular.module("openshiftConsole")
44
.directive("oscPersistentVolumeClaim",
5-
function(DataService,
5+
function($filter,
6+
DataService,
7+
LimitRangesService,
68
ModalsService) {
79
return {
810
restrict: 'E',
911
scope: {
10-
claim: "=model"
12+
claim: "=model",
13+
projectName: "="
1114
},
1215
templateUrl: 'views/directives/osc-persistent-volume-claim.html',
1316
link: function(scope) {
17+
var amountAndUnit = $filter('amountAndUnit');
18+
var usageValue = $filter('usageValue');
19+
1420
scope.storageClasses = [];
1521
scope.claim.unit = 'Gi';
1622
scope.units = [{
@@ -53,9 +59,54 @@ angular.module("openshiftConsole")
5359
ModalsService.showComputeUnitsHelp();
5460
};
5561

62+
var validateLimitRange = function() {
63+
// Use usageValue filter to normalize units for comparison.
64+
var value = scope.claim.amount && usageValue(scope.claim.amount + scope.claim.unit);
65+
var min = _.has(scope, 'limits.min') && usageValue(scope.limits.min);
66+
var max = _.has(scope, 'limits.max') && usageValue(scope.limits.max);
67+
var minValid = true;
68+
var maxValid = true;
69+
70+
// Test against limit range min if defined.
71+
if (value && min) {
72+
minValid = value >= min;
73+
}
74+
75+
// Test against limit range max if defined.
76+
if (value && max) {
77+
maxValid = value <= max;
78+
}
79+
80+
scope.persistentVolumeClaimForm.capacity.$setValidity('limitRangeMin', minValid);
81+
scope.persistentVolumeClaimForm.capacity.$setValidity('limitRangeMax', maxValid);
82+
};
83+
5684
DataService.list({group: 'storage.k8s.io', resource: 'storageclasses'}, {}, function(storageClasses) {
5785
scope.storageClasses = storageClasses.by('metadata.name');
5886
}, {errorNotification: false});
87+
88+
DataService.list('limitranges', { namespace: scope.projectName }, function(limitRangeData) {
89+
var limitRanges = limitRangeData.by('metadata.name');
90+
if (_.isEmpty(limitRanges)) {
91+
return;
92+
}
93+
94+
scope.limits = LimitRangesService.getEffectiveLimitRange(limitRanges, 'storage', 'PersistentVolumeClaim');
95+
// If min === max, set the capacity to the required value and make the field readonly.
96+
var requiredAmountAndUnit;
97+
if (scope.limits.min && scope.limits.max) {
98+
var minUsage = usageValue(scope.limits.min);
99+
var maxUsage = usageValue(scope.limits.max);
100+
if (minUsage === maxUsage) {
101+
requiredAmountAndUnit = amountAndUnit(scope.limits.max);
102+
scope.claim.amount = Number(requiredAmountAndUnit[0]);
103+
scope.claim.unit = requiredAmountAndUnit[1];
104+
scope.capacityReadOnly = true;
105+
}
106+
}
107+
108+
scope.$watchGroup(['claim.amount', 'claim.unit'], validateLimitRange);
109+
});
59110
}
60111
};
61112
});

app/styles/_forms.less

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
.static-form-value-large {
2+
.h3();
3+
margin-top: 3px;
4+
}
5+
16
.copy-to-clipboard input.form-control:read-only {
27
background-color: white;
38
color: @text-color;

app/views/create-persistent-volume-claim.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ <h1>Create Storage</h1>
2121
</div>
2222
<form name="createPersistentVolumeClaimForm" class="mar-top-lg">
2323
<fieldset ng-disabled="disableInputs">
24-
<osc-persistent-volume-claim model="claim"></osc-persistent-volume-claim>
24+
<osc-persistent-volume-claim model="claim" project-name="projectName"></osc-persistent-volume-claim>
2525
<div class="button-group gutter-bottom">
2626
<button type="submit"
2727
class="btn btn-primary btn-lg"

app/views/directives/osc-persistent-volume-claim.html

+53-24
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
</div>
6868

6969
<div class="form-group" >
70-
<label class="required">Access Mode</label><br/>
70+
<label class="required">Access Mode</label>
7171
<div class="radio">
7272

7373
<label class="radio-inline">
@@ -92,21 +92,38 @@
9292
</div>
9393

9494
<!-- capacity -->
95-
<div class="form-group">
95+
<div ng-if="capacityReadOnly" class="form-group mar-bottom-xl">
96+
<label>Size</label>
97+
<div class="static-form-value-large">
98+
{{claim.amount}} {{claim.unit | humanizeUnit : 'storage'}}
99+
<small>(cannot be changed)</small>
100+
</div>
101+
</div>
102+
<div ng-if="!capacityReadOnly" class="form-group">
96103
<fieldset class="form-inline compute-resource">
97-
<label class="required">Size</label>
98-
<div class="resource-size">
99-
<div class="resource-amount" ng-class="{ 'has-error': persistentVolumeClaimForm.capacity.$invalid && persistentVolumeClaimForm.capacity.$touched && !claimDisabled }">
100-
<label class="sr-only">Amount</label>
104+
<label class="required">
105+
Size
106+
<small ng-if="limits.min && limits.max">
107+
{{limits.min | usageWithUnits : 'storage'}} min to {{limits.max | usageWithUnits : 'storage'}} max
108+
</small>
109+
<small ng-if="limits.min && !limits.max">
110+
Min: {{limits.min | usageWithUnits : 'storage'}}
111+
</small>
112+
<small ng-if="limits.max && !limits.min">
113+
Max: {{limits.max | usageWithUnits : 'storage'}}
114+
</small>
115+
</label>
116+
<div class="resource-size" ng-class="{ 'has-error': persistentVolumeClaimForm.capacity.$invalid && persistentVolumeClaimForm.capacity.$touched && !claimDisabled }">
117+
<div class="resource-amount">
118+
<label for="claim-amount" class="sr-only">Amount</label>
101119
<input type="number"
102120
name="capacity"
103-
ng-attr-id="claim-amount"
121+
id="claim-amount"
104122
ng-model="claim.amount"
105-
ng-required="true"
123+
required
106124
min="0"
107-
ng-attr-placeholder="10"
108125
class="form-control"
109-
ng-attr-aria-describedby="claim-capacity-help">
126+
aria-describedby="claim-capacity-help">
110127
</div>
111128
<div class="resource-unit">
112129
<label class="sr-only" >Unit</label>
@@ -120,20 +137,32 @@
120137
</div>
121138
<div id="claim-capacity-help" class="help-block">
122139
Desired storage capacity.
123-
</div>
124-
<div class="has-error" ng-show="persistentVolumeClaimForm.capacity.$error.number && persistentVolumeClaimForm.capacity.$touched && !claimDisabled">
125-
<span class="help-block">
126-
Must be a number.
127-
</span>
128-
</div>
129-
<div class="has-error" ng-show="persistentVolumeClaimForm.capacity.$error.min && persistentVolumeClaimForm.capacity.$touched && !claimDisabled">
130-
<span class="help-block">
131-
Must be a positive number.
132-
</span>
133-
</div>
134-
<div class="learn-more-block mar-top-sm">
135-
<a href="" ng-click="showComputeUnitsHelp()">What are GiB?</a>
136-
</div>
140+
</div>
141+
<div ng-if="persistentVolumeClaimForm.capacity.$touched && !claimDisabled">
142+
<div class="has-error" ng-show="persistentVolumeClaimForm.capacity.$error.number">
143+
<span class="help-block">
144+
Must be a number.
145+
</span>
146+
</div>
147+
<div class="has-error" ng-show="persistentVolumeClaimForm.capacity.$error.min">
148+
<span class="help-block">
149+
Must be a positive number.
150+
</span>
151+
</div>
152+
<div ng-if="persistentVolumeClaimForm.capacity.$error.limitRangeMin" class="has-error">
153+
<span class="help-block">
154+
Can't be less than {{limits.min | usageWithUnits : 'storage'}}.
155+
</span>
156+
</div>
157+
<div ng-if="persistentVolumeClaimForm.capacity.$error.limitRangeMax" class="has-error">
158+
<span class="help-block">
159+
Can't be greater than {{limits.max | usageWithUnits : 'storage'}}.
160+
</span>
161+
</div>
162+
</div>
163+
<div class="learn-more-block mar-top-sm">
164+
<a href="" ng-click="showComputeUnitsHelp()">What are GiB?</a>
165+
</div>
137166
</fieldset>
138167
</div>
139168
<!--advanced options-->

dist/scripts/scripts.js

+29-9
Original file line numberDiff line numberDiff line change
@@ -10063,15 +10063,17 @@ _.set(a, "model.service", c);
1006310063
});
1006410064
}
1006510065
};
10066-
}), angular.module("openshiftConsole").directive("oscPersistentVolumeClaim", [ "DataService", "ModalsService", function(a, b) {
10066+
}), angular.module("openshiftConsole").directive("oscPersistentVolumeClaim", [ "$filter", "DataService", "LimitRangesService", "ModalsService", function(a, b, c, d) {
1006710067
return {
1006810068
restrict:"E",
1006910069
scope:{
10070-
claim:"=model"
10070+
claim:"=model",
10071+
projectName:"="
1007110072
},
1007210073
templateUrl:"views/directives/osc-persistent-volume-claim.html",
10073-
link:function(c) {
10074-
c.storageClasses = [], c.claim.unit = "Gi", c.units = [ {
10074+
link:function(e) {
10075+
var f = a("amountAndUnit"), g = a("usageValue");
10076+
e.storageClasses = [], e.claim.unit = "Gi", e.units = [ {
1007510077
value:"Mi",
1007610078
label:"MiB"
1007710079
}, {
@@ -10089,7 +10091,7 @@ label:"GB"
1008910091
}, {
1009010092
value:"T",
1009110093
label:"TB"
10092-
} ], c.claim.selectedLabels = [], c.groupUnits = function(a) {
10094+
} ], e.claim.selectedLabels = [], e.groupUnits = function(a) {
1009310095
switch (a.value) {
1009410096
case "Mi":
1009510097
case "Gi":
@@ -10102,15 +10104,33 @@ case "T":
1010210104
return "Decimal Units";
1010310105
}
1010410106
return "";
10105-
}, c.showComputeUnitsHelp = function() {
10106-
b.showComputeUnitsHelp();
10107-
}, a.list({
10107+
}, e.showComputeUnitsHelp = function() {
10108+
d.showComputeUnitsHelp();
10109+
};
10110+
var h = function() {
10111+
var a = e.claim.amount && g(e.claim.amount + e.claim.unit), b = _.has(e, "limits.min") && g(e.limits.min), c = _.has(e, "limits.max") && g(e.limits.max), d = !0, f = !0;
10112+
a && b && (d = a >= b), a && c && (f = a <= c), e.persistentVolumeClaimForm.capacity.$setValidity("limitRangeMin", d), e.persistentVolumeClaimForm.capacity.$setValidity("limitRangeMax", f);
10113+
};
10114+
b.list({
1010810115
group:"storage.k8s.io",
1010910116
resource:"storageclasses"
1011010117
}, {}, function(a) {
10111-
c.storageClasses = a.by("metadata.name");
10118+
e.storageClasses = a.by("metadata.name");
1011210119
}, {
1011310120
errorNotification:!1
10121+
}), b.list("limitranges", {
10122+
namespace:e.projectName
10123+
}, function(a) {
10124+
var b = a.by("metadata.name");
10125+
if (!_.isEmpty(b)) {
10126+
e.limits = c.getEffectiveLimitRange(b, "storage", "PersistentVolumeClaim");
10127+
var d;
10128+
if (e.limits.min && e.limits.max) {
10129+
var i = g(e.limits.min), j = g(e.limits.max);
10130+
i === j && (d = f(e.limits.max), e.claim.amount = Number(d[0]), e.claim.unit = d[1], e.capacityReadOnly = !0);
10131+
}
10132+
e.$watchGroup([ "claim.amount", "claim.unit" ], h);
10133+
}
1011410134
});
1011510135
}
1011610136
};

dist/scripts/templates.js

+40-10
Original file line numberDiff line numberDiff line change
@@ -4531,7 +4531,7 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function(
45314531
"</div>\n" +
45324532
"<form name=\"createPersistentVolumeClaimForm\" class=\"mar-top-lg\">\n" +
45334533
"<fieldset ng-disabled=\"disableInputs\">\n" +
4534-
"<osc-persistent-volume-claim model=\"claim\"></osc-persistent-volume-claim>\n" +
4534+
"<osc-persistent-volume-claim model=\"claim\" project-name=\"projectName\"></osc-persistent-volume-claim>\n" +
45354535
"<div class=\"button-group gutter-bottom\">\n" +
45364536
"<button type=\"submit\" class=\"btn btn-primary btn-lg\" ng-click=\"createPersistentVolumeClaim()\" ng-disabled=\"createPersistentVolumeClaimForm.$invalid || disableInputs\" value=\"\">Create</button>\n" +
45374537
"<a class=\"btn btn-default btn-lg\" href=\"\" back>Cancel</a>\n" +
@@ -7547,7 +7547,7 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function(
75477547
"</div>\n" +
75487548
"</div>\n" +
75497549
"<div class=\"form-group\">\n" +
7550-
"<label class=\"required\">Access Mode</label><br/>\n" +
7550+
"<label class=\"required\">Access Mode</label>\n" +
75517551
"<div class=\"radio\">\n" +
75527552
"<label class=\"radio-inline\">\n" +
75537553
"<input type=\"radio\" name=\"accessModes\" ng-model=\"claim.accessModes\" value=\"ReadWriteOnce\" aria-describedby=\"access-modes-help\" ng-checked=\"true\">\n" +
@@ -7567,13 +7567,31 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function(
75677567
"</div>\n" +
75687568
"</div>\n" +
75697569
"\n" +
7570-
"<div class=\"form-group\">\n" +
7570+
"<div ng-if=\"capacityReadOnly\" class=\"form-group mar-bottom-xl\">\n" +
7571+
"<label>Size</label>\n" +
7572+
"<div class=\"static-form-value-large\">\n" +
7573+
"{{claim.amount}} {{claim.unit | humanizeUnit : 'storage'}}\n" +
7574+
"<small>(cannot be changed)</small>\n" +
7575+
"</div>\n" +
7576+
"</div>\n" +
7577+
"<div ng-if=\"!capacityReadOnly\" class=\"form-group\">\n" +
75717578
"<fieldset class=\"form-inline compute-resource\">\n" +
7572-
"<label class=\"required\">Size</label>\n" +
7573-
"<div class=\"resource-size\">\n" +
7574-
"<div class=\"resource-amount\" ng-class=\"{ 'has-error': persistentVolumeClaimForm.capacity.$invalid && persistentVolumeClaimForm.capacity.$touched && !claimDisabled }\">\n" +
7575-
"<label class=\"sr-only\">Amount</label>\n" +
7576-
"<input type=\"number\" name=\"capacity\" ng-attr-id=\"claim-amount\" ng-model=\"claim.amount\" ng-required=\"true\" min=\"0\" ng-attr-placeholder=\"10\" class=\"form-control\" ng-attr-aria-describedby=\"claim-capacity-help\">\n" +
7579+
"<label class=\"required\">\n" +
7580+
"Size\n" +
7581+
"<small ng-if=\"limits.min && limits.max\">\n" +
7582+
"{{limits.min | usageWithUnits : 'storage'}} min to {{limits.max | usageWithUnits : 'storage'}} max\n" +
7583+
"</small>\n" +
7584+
"<small ng-if=\"limits.min && !limits.max\">\n" +
7585+
"Min: {{limits.min | usageWithUnits : 'storage'}}\n" +
7586+
"</small>\n" +
7587+
"<small ng-if=\"limits.max && !limits.min\">\n" +
7588+
"Max: {{limits.max | usageWithUnits : 'storage'}}\n" +
7589+
"</small>\n" +
7590+
"</label>\n" +
7591+
"<div class=\"resource-size\" ng-class=\"{ 'has-error': persistentVolumeClaimForm.capacity.$invalid && persistentVolumeClaimForm.capacity.$touched && !claimDisabled }\">\n" +
7592+
"<div class=\"resource-amount\">\n" +
7593+
"<label for=\"claim-amount\" class=\"sr-only\">Amount</label>\n" +
7594+
"<input type=\"number\" name=\"capacity\" id=\"claim-amount\" ng-model=\"claim.amount\" required min=\"0\" class=\"form-control\" aria-describedby=\"claim-capacity-help\">\n" +
75777595
"</div>\n" +
75787596
"<div class=\"resource-unit\">\n" +
75797597
"<label class=\"sr-only\">Unit</label>\n" +
@@ -7588,16 +7606,28 @@ angular.module('openshiftConsoleTemplates', []).run(['$templateCache', function(
75887606
"<div id=\"claim-capacity-help\" class=\"help-block\">\n" +
75897607
"Desired storage capacity.\n" +
75907608
"</div>\n" +
7591-
"<div class=\"has-error\" ng-show=\"persistentVolumeClaimForm.capacity.$error.number && persistentVolumeClaimForm.capacity.$touched && !claimDisabled\">\n" +
7609+
"<div ng-if=\"persistentVolumeClaimForm.capacity.$touched && !claimDisabled\">\n" +
7610+
"<div class=\"has-error\" ng-show=\"persistentVolumeClaimForm.capacity.$error.number\">\n" +
75927611
"<span class=\"help-block\">\n" +
75937612
"Must be a number.\n" +
75947613
"</span>\n" +
75957614
"</div>\n" +
7596-
"<div class=\"has-error\" ng-show=\"persistentVolumeClaimForm.capacity.$error.min && persistentVolumeClaimForm.capacity.$touched && !claimDisabled\">\n" +
7615+
"<div class=\"has-error\" ng-show=\"persistentVolumeClaimForm.capacity.$error.min\">\n" +
75977616
"<span class=\"help-block\">\n" +
75987617
"Must be a positive number.\n" +
75997618
"</span>\n" +
76007619
"</div>\n" +
7620+
"<div ng-if=\"persistentVolumeClaimForm.capacity.$error.limitRangeMin\" class=\"has-error\">\n" +
7621+
"<span class=\"help-block\">\n" +
7622+
"Can't be less than {{limits.min | usageWithUnits : 'storage'}}.\n" +
7623+
"</span>\n" +
7624+
"</div>\n" +
7625+
"<div ng-if=\"persistentVolumeClaimForm.capacity.$error.limitRangeMax\" class=\"has-error\">\n" +
7626+
"<span class=\"help-block\">\n" +
7627+
"Can't be greater than {{limits.max | usageWithUnits : 'storage'}}.\n" +
7628+
"</span>\n" +
7629+
"</div>\n" +
7630+
"</div>\n" +
76017631
"<div class=\"learn-more-block mar-top-sm\">\n" +
76027632
"<a href=\"\" ng-click=\"showComputeUnitsHelp()\">What are GiB?</a>\n" +
76037633
"</div>\n" +

dist/styles/main.css

+2
Original file line numberDiff line numberDiff line change
@@ -3579,6 +3579,8 @@ to{transform:rotate(359deg)}
35793579
.btn-file input[type=file]{position:absolute;top:0;right:0;min-width:100%;min-height:100%;font-size:100px;text-align:right;filter:alpha(opacity=0);opacity:0;cursor:inherit;display:block}
35803580
.btn-flat-default{border:1px solid transparent}
35813581
.btn-flat-default:focus,.btn-flat-default:hover{background-color:#f7f7f7;border-color:#e7e7e7}
3582+
.static-form-value-large{font-family:inherit;font-weight:500;line-height:1.1;color:inherit;margin-bottom:10.5px;font-size:16px;margin-top:3px}
3583+
.static-form-value-large .small,.static-form-value-large small{font-weight:400;line-height:1;color:#9c9c9c;font-size:65%}
35823584
.copy-to-clipboard input.form-control:read-only{background-color:#fff;color:#363636}
35833585
.copy-to-clipboard-multiline{position:relative;width:100%}
35843586
.copy-to-clipboard-multiline a{box-shadow:none;position:absolute;right:0;top:0}

0 commit comments

Comments
 (0)