Skip to content

Commit 71ac457

Browse files
committed
Support EnvFrom in the Env Editors
Add dropdown support to give the ability to add bulk additions within the environment editors
1 parent be4c893 commit 71ac457

File tree

7 files changed

+1073
-608
lines changed

7 files changed

+1073
-608
lines changed

app/index.html

+1
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ <h1>JavaScript Required</h1>
307307
<script src="scripts/directives/deleteLink.js"></script>
308308
<script src="scripts/directives/editWebhookTriggers.js"></script>
309309
<script src="scripts/directives/editConfigMap.js"></script>
310+
<script src="scripts/directives/editEnvironmentFrom.js"></script>
310311
<script src="scripts/directives/events.js"></script>
311312
<script src="scripts/directives/eventsSidebar.js"></script>
312313
<script src="scripts/directives/eventsBadge.js"></script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
"use strict";
2+
(function() {
3+
angular.module("openshiftConsole").component('editEnvironmentFrom', {
4+
controller: [
5+
'$attrs',
6+
'$filter',
7+
'$scope',
8+
'keyValueEditorUtils',
9+
EditEnvironmentFrom
10+
],
11+
//controllerAs: 'ctrl',
12+
bindings: {
13+
addRowLink: '@',
14+
entries: '=',
15+
envFromSelectorOptions: '<',
16+
selectorPlaceholder: '@'
17+
},
18+
templateUrl: 'views/directives/edit-environment-from.html'
19+
});
20+
21+
function EditEnvironmentFrom($attrs,
22+
$filter,
23+
$scope,
24+
utils) {
25+
var ctrl = this;
26+
27+
var canI = $filter('canI');
28+
var humanizeKind = $filter('humanizeKind');
29+
30+
ctrl.$id = $scope.$id;
31+
ctrl.setFocusClass = 'edit-environment-from-set-focus-' + ctrl.$id;
32+
33+
var addEntry = function(entries, entry) {
34+
entries && entries.push(entry || {});
35+
};
36+
37+
ctrl.onAddRow = function() {
38+
addEntry(ctrl.envFromEntries);
39+
utils.setFocusOn('.'+ ctrl.setFocusClass);
40+
};
41+
42+
ctrl.deleteEntry = function(start, deleteCount) {
43+
if(ctrl.entries && !ctrl.entries.length) {
44+
return;
45+
}
46+
47+
ctrl.envFromEntries.splice(start, deleteCount);
48+
if(!ctrl.envFromEntries.length && ctrl.addRowLink) {
49+
addEntry(ctrl.envFromEntries);
50+
}
51+
52+
ctrl.updateEntries(ctrl.envFromEntries);
53+
$scope.forms.editEnvironmentFrom.$setDirty();
54+
};
55+
56+
ctrl.isEnvFromReadonly = function(entry) {
57+
return ctrl.isReadonlyAny ||
58+
entry.isReadonlyValue === true ||
59+
((entry.secretRef || entry.configMapRef) && !entry.selectedEnvFrom) ||
60+
_.isEmpty(ctrl.envFromSelectorOptions);
61+
};
62+
63+
ctrl.groupByKind = function(object) {
64+
return humanizeKind(object.kind);
65+
};
66+
67+
ctrl.envFromObjectSelected = function(index, entry, selected) {
68+
var newEnvFrom = {};
69+
70+
switch (selected.kind) {
71+
case 'Secret':
72+
newEnvFrom.secretRef = {
73+
name: selected.metadata.name
74+
};
75+
delete ctrl.envFromEntries[index].configMapRef;
76+
break;
77+
case 'ConfigMap':
78+
newEnvFrom.configMapRef = {
79+
name: selected.metadata.name
80+
};
81+
delete ctrl.envFromEntries[index].secretRef;
82+
break;
83+
}
84+
85+
_.assign(ctrl.envFromEntries[index], newEnvFrom);
86+
ctrl.updateEntries(ctrl.envFromEntries);
87+
};
88+
89+
ctrl.updateEntries = function(entries) {
90+
ctrl.entries = _.filter(_.clone(entries), function (val) {
91+
return val.secretRef || val.configMapRef;
92+
});
93+
};
94+
95+
ctrl.updateEnvFromEntries = function(entries) {
96+
ctrl.envFromEntries = _.clone(entries || []);
97+
98+
if(!ctrl.envFromEntries.length) {
99+
addEntry(ctrl.envFromEntries);
100+
}
101+
102+
_.each(ctrl.envFromEntries, function(entry) {
103+
if(entry) {
104+
if (entry.configMapRef) {
105+
entry.isReadonlyValue = !canI('configmaps', 'get');
106+
}
107+
108+
if (entry.secretRef) {
109+
entry.isReadonlyValue = !canI('secrets', 'get');
110+
}
111+
}
112+
});
113+
};
114+
115+
var getReferenceValue = function(option) {
116+
var referenceValue;
117+
118+
switch(option.kind) {
119+
case 'ConfigMap':
120+
referenceValue = _.find(ctrl.envFromEntries, {configMapRef: {name: option.metadata.name}});
121+
break;
122+
case 'Secret':
123+
referenceValue = _.find(ctrl.envFromEntries, {secretRef: {name: option.metadata.name}});
124+
break;
125+
}
126+
127+
return referenceValue;
128+
};
129+
130+
ctrl.checkEntries = function(option) {
131+
return !!(getReferenceValue(option));
132+
};
133+
134+
var findReferenceValueForEntries = function(entries, envFromSelectorOptions) {
135+
_.each(envFromSelectorOptions, function(option) {
136+
var referenceValue = getReferenceValue(option);
137+
138+
if (referenceValue) {
139+
_.set(referenceValue, 'selectedEnvFrom', option);
140+
}
141+
});
142+
};
143+
144+
angular.extend($scope, {
145+
dragControlListeners: {
146+
accept: function (sourceItemHandleScope, destSortableScope) {
147+
return sourceItemHandleScope.itemScope.sortableScope.$id === destSortableScope.$id;
148+
},
149+
orderChanged: function() {
150+
$scope.forms.editEnvironmentFrom.$setDirty();
151+
}
152+
}
153+
});
154+
155+
ctrl.$onInit = function() {
156+
ctrl.updateEnvFromEntries(ctrl.entries);
157+
findReferenceValueForEntries(ctrl.envFromEntries, ctrl.envFromSelectorOptions);
158+
159+
if('cannotAdd' in $attrs) {
160+
ctrl.cannotAdd = true;
161+
}
162+
163+
if('cannotDelete' in $attrs) {
164+
ctrl.cannotDeleteAny = true;
165+
}
166+
167+
if('cannotSort' in $attrs) {
168+
ctrl.cannotSort = true;
169+
}
170+
171+
if('isReadonly' in $attrs) {
172+
ctrl.isReadonlyAny = true;
173+
}
174+
175+
if('showHeader' in $attrs) {
176+
ctrl.showHeader = true;
177+
}
178+
179+
if(ctrl.envFromEntries && !ctrl.envFromEntries.length) {
180+
addEntry(ctrl.envFromEntries);
181+
}
182+
};
183+
184+
ctrl.$onChanges = function(changes) {
185+
if(changes.entries) {
186+
ctrl.updateEnvFromEntries(changes.entries.currentValue);
187+
}
188+
189+
if(changes.envFromSelectorOptions) {
190+
findReferenceValueForEntries(ctrl.envFromEntries, changes.envFromSelectorOptions.currentValue);
191+
}
192+
};
193+
}
194+
})();
195+

app/scripts/services/environment.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ angular.module("openshiftConsole")
2121
var containers = getContainers(object);
2222
_.each(containers, function(container) {
2323
container.env = container.env || [];
24+
container.envFrom = container.envFrom || [];
2425
});
2526
},
2627

@@ -50,7 +51,7 @@ angular.module("openshiftConsole")
5051
return false;
5152
}
5253

53-
var i, leftEnv, rightEnv;
54+
var i, leftEnv, rightEnv, leftEnvFrom, rightEnvFrom;
5455
for (i = 0; i < leftContainers.length; i++) {
5556
// If a container name has changed, consider it a conflict.
5657
if (leftContainers[i].name !== rightContainers[i].name) {
@@ -60,7 +61,11 @@ angular.module("openshiftConsole")
6061
// Check if any of the variable names or values are different.
6162
leftEnv = leftContainers[i].env || [];
6263
rightEnv = rightContainers[i].env || [];
63-
if (!_.isEqual(leftEnv, rightEnv)) {
64+
65+
leftEnvFrom = leftContainers[i].envFrom || [];
66+
rightEnvFrom = rightContainers[i].envFrom || [];
67+
68+
if (!_.isEqual(leftEnv, rightEnv) || !_.isEqual(leftEnvFrom, rightEnvFrom)) {
6469
return false;
6570
}
6671
}
@@ -78,6 +83,7 @@ angular.module("openshiftConsole")
7883
var targetContainers = getContainers(copy);
7984
for (i = 0; i < targetContainers.length; i++) {
8085
targetContainers[i].env = _.get(sourceContainers, [i, 'env'], []);
86+
targetContainers[i].envFrom = _.get(sourceContainers, [i, 'envFrom'], []);
8187
}
8288

8389
return copy;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<ng-form name="forms.editEnvironmentFrom" novalidate>
2+
<div
3+
ng-if="$ctrl.showHeader"
4+
class="key-value-editor-entry key-value-editor-entry-header">
5+
<div class="form-group key-value-editor-header value-header">
6+
<div class="input-group">
7+
<span class="help-block">{{$ctrl.selectorPlaceholder}}</span>
8+
</div>
9+
</div>
10+
</div>
11+
12+
<div ng-model="$ctrl.entries" class="key-value-editor" as-sortable="dragControlListeners">
13+
<div
14+
class="key-value-editor-entry"
15+
ng-class-odd="'odd'"
16+
ng-class-even="'even'"
17+
ng-repeat="entry in $ctrl.envFromEntries"
18+
as-sortable-item>
19+
20+
<div
21+
class="form-group key-value-editor-input"
22+
ng-class="{ 'has-error': (forms.editEnvironmentFrom[uniqueForValue(unique, $index)].$invalid && forms.editEnvironmentFrom[uniqueForValue(unique, $index)].$touched) }">
23+
<div ng-if="$ctrl.isEnvFromReadonly(entry)" class="faux-input-group">
24+
<div class="faux-form-control readonly">
25+
Set to values in {{entry.selectedEnvFrom.kind | humanizeKind : true | lowercase}}
26+
<span
27+
ng-if="!('configmaps' | canI : 'get') || !('secrets' | canI : 'get')">
28+
{{entry.configMapRef.name || entry.secretRef.name}}
29+
</span>
30+
<a
31+
ng-if="'configmaps' | canI : 'get'"
32+
ng-href="{{entry.selectedEnvFrom | navigateResourceURL}}">
33+
{{entry.configMapRef.name || entry.secretRef.name}}
34+
</a>
35+
</div>
36+
</div>
37+
38+
<div ng-if="!$ctrl.isEnvFromReadonly(entry)">
39+
<div class="ui-select">
40+
<ui-select ng-model="entry.selectedEnvFrom"
41+
ng-required="entry.selectedEnvFrom"
42+
on-select="$ctrl.envFromObjectSelected($index, entry, $select.selected)"
43+
ng-class="{'{{$ctrl.setFocusClass}}' : $last}">
44+
<ui-select-match placeholder="Select a resource">
45+
<span>
46+
{{$select.selected.metadata.name}}
47+
<small class="text-muted">&ndash; {{$select.selected.kind | humanizeKind : true}}</small>
48+
</span>
49+
</ui-select-match>
50+
<ui-select-choices
51+
ui-disable-choice="$ctrl.checkEntries(source)"
52+
repeat="source in $ctrl.envFromSelectorOptions | filter : { metadata: { name: $select.search } } track by (source | uid)"
53+
group-by="$ctrl.groupByKind">
54+
<span ng-bind-html="source.metadata.name | highlight : $select.search"></span>
55+
</ui-select-choices>
56+
</ui-select>
57+
</div>
58+
</div>
59+
60+
<div>
61+
<span
62+
ng-if="(!$ctrl.cannotSort) && ($ctrl.entries.length > 1)"
63+
class="fa fa-bars sort-row"
64+
role="button"
65+
aria-label="Move row"
66+
aria-grabbed="false"
67+
as-sortable-item-handle></span>
68+
<a
69+
href=""
70+
class="pficon pficon-close delete-row as-sortable-item-delete"
71+
role="button"
72+
aria-label="Delete row"
73+
ng-hide="$ctrl.cannotDeleteAny"
74+
ng-click="$ctrl.deleteEntry($index, 1)"></a>
75+
<a
76+
ng-href="{{entry.selectedEnvFrom | navigateResourceURL}}"
77+
class="pficon"
78+
ng-show="entry.selectedEnvFrom"
79+
ng-click="$ctrl.viewDetail(entry)">View {{entry.selectedEnvFrom.kind | humanizeKind : true}}</a>
80+
</div>
81+
</div>
82+
</div>
83+
84+
<div class="key-value-editor-entry form-group" ng-if="(!$ctrl.cannotAdd)">
85+
<a
86+
href=""
87+
class="add-row-link"
88+
role="button"
89+
aria-label="Add row"
90+
ng-click="$ctrl.onAddRow()">{{ $ctrl.addRowLink }}</a>
91+
</div>
92+
</div>
93+
</ng-form>
94+

app/views/directives/edit-environment-variables.html

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<confirm-on-exit ng-if="$ctrl.canIUpdate && !$ctrl.ngReadonly" dirty="$ctrl.form.$dirty"></confirm-on-exit>
33
<div ng-repeat="container in $ctrl.containers">
44
<h3>Container {{container.name}}</h3>
5+
6+
<h4>Variables</h4>
57
<div ng-if="!$ctrl.canIUpdate || $ctrl.ngReadonly">
68
<span ng-if="!container.env.length">
79
No environment variables set in the {{$ctrl.apiObject.kind | humanizeKind}}
@@ -32,6 +34,21 @@ <h3>Container {{container.name}}</h3>
3234
add-row-with-selectors-link="Add Environment Variable Using a Config Map or Secret"
3335
show-header>
3436
</key-value-editor>
37+
38+
<h4>
39+
Environment From
40+
<span class="pficon pficon-info"
41+
aria-hidden="true"
42+
data-toggle="tooltip"
43+
data-original-title="Environment From lets you add all key value pairs from a config map or secret."></span>
44+
</h4>
45+
<edit-environment-from
46+
entries="container.envFrom"
47+
selector-placeholder="Secret/Config Map"
48+
env-from-selector-options="$ctrl.valueFromObjects"
49+
add-row-link="Add ALL Values from a Resource"
50+
show-header>
51+
</edit-environment-from>
3552
</div>
3653
<button
3754
class="btn btn-default"

0 commit comments

Comments
 (0)