Skip to content

Commit 80e2c8e

Browse files
committed
feat(ui): use list for env vars
1 parent ab17bee commit 80e2c8e

File tree

5 files changed

+211
-67
lines changed

5 files changed

+211
-67
lines changed

db_lib/AnsiblePlaybook.go

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ func (p AnsiblePlaybook) makeCmd(command string, args []string, environmentVars
2727
cmd.Env = append(cmd.Env, fmt.Sprintf("PWD=%s", cmd.Dir))
2828
cmd.Env = append(cmd.Env, "PYTHONUNBUFFERED=1")
2929
cmd.Env = append(cmd.Env, "ANSIBLE_FORCE_COLOR=True")
30+
cmd.Env = append(cmd.Env, "ANSIBLE_SSH_ARGS=\"-o BatchMode=yes\"")
31+
3032
if environmentVars != nil {
3133
cmd.Env = append(cmd.Env, *environmentVars...)
3234
}

web/src/components/EnvironmentForm.vue

+185-54
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,31 @@
2020
class="mb-4"
2121
></v-text-field>
2222

23-
<v-subheader class="pl-0">
23+
<v-subheader class="px-0">
2424
{{ $t('extraVariables') }}
25+
26+
<v-tooltip bottom color="black" open-delay="300">
27+
<template v-slot:activator="{ on, attrs }">
28+
<v-icon
29+
class="ml-1"
30+
v-bind="attrs"
31+
v-on="on"
32+
>mdi-help-circle</v-icon>
33+
</template>
34+
<span>Variables passed via <code>--extra-vars</code>.</span>
35+
</v-tooltip>
36+
37+
<v-spacer />
38+
39+
<v-btn-toggle
40+
v-model="extraVarsEditMode"
41+
tile
42+
group
43+
>
44+
<v-btn value="json" small class="mr-0" style="border-radius: 4px;" disabled>
45+
JSON
46+
</v-btn>
47+
</v-btn-toggle>
2548
</v-subheader>
2649

2750
<codemirror
@@ -31,65 +54,123 @@
3154
:placeholder="$t('enterExtraVariablesJson')"
3255
/>
3356

34-
<div class="mt-4">
35-
<div class="d-flex flex-row justify-space-between">
36-
<div>
37-
<div style="line-height: 1.1;" class="pl-1">
38-
Avoid host key checking by the tools Ansible uses to connect to the host.
39-
</div>
40-
<code>"ANSIBLE_HOST_KEY_CHECKING": false</code>
41-
</div>
42-
<v-btn
43-
color="primary"
44-
@click="setExtraVar('ANSIBLE_HOST_KEY_CHECKING', false)"
45-
>Set variable</v-btn>
46-
</div>
47-
</div>
57+
<div>
4858

49-
<v-alert
50-
dense
51-
text
52-
type="info"
53-
class="mt-4"
54-
>
55-
{{ $t('environmentAndExtraVariablesMustBeValidJsonExample') }}
56-
<pre style="font-size: 14px;">{
57-
"var_available_in_playbook_1": 1245,
58-
"var_available_in_playbook_2": "test"
59-
}</pre>
60-
</v-alert>
61-
62-
<div class="mt-4" v-if="!advancedOptions">
63-
<a @click="advancedOptions = true">
64-
{{ $t('advanced') }}
65-
<v-icon style="transform: translateY(-1px)">mdi-chevron-right</v-icon>
66-
</a>
67-
</div>
68-
69-
<div class="mt-4" v-else>
70-
<a @click="advancedOptions = false">
71-
{{ $t('hide') }}
72-
<v-icon style="transform: translateY(-1px)">mdi-chevron-up</v-icon>
73-
</a>
74-
</div>
75-
76-
<div v-if="advancedOptions">
77-
78-
<v-subheader class="pl-0">
59+
<v-subheader class="px-0 mt-4">
7960
{{ $t('environmentVariables') }}
61+
62+
<v-tooltip bottom color="black" open-delay="300">
63+
<template v-slot:activator="{ on, attrs }">
64+
<v-icon
65+
class="ml-1"
66+
v-bind="attrs"
67+
v-on="on"
68+
color="lightgray"
69+
>mdi-help-circle</v-icon>
70+
</template>
71+
<span>Variables passed as process environment variables.</span>
72+
</v-tooltip>
8073
</v-subheader>
8174

82-
<codemirror
83-
:style="{ border: '1px solid lightgray' }"
84-
v-model="env"
85-
:options="cmOptions"
86-
:placeholder="$t('enterEnvJson')"
87-
/>
75+
<v-chip-group
76+
v-model="predefinedEnvVars"
77+
column
78+
multiple
79+
class="EnvironmentForm__predefinedEnvVars"
80+
>
81+
<v-chip
82+
filter
83+
outlined
84+
v-for="item in PREDEFINED_ENV_VARS"
85+
:key="item.name"
86+
>
87+
<span class="EnvironmentForm__predefinedEnvVarsValue">
88+
{{ item.name }}={{ item.value }}
89+
</span>
90+
<v-tooltip
91+
bottom
92+
color="black"
93+
:max-width="400"
94+
open-delay="300"
95+
>
96+
<template v-slot:activator="{ on, attrs }">
97+
<v-icon
98+
class="ml-2"
99+
v-bind="attrs"
100+
v-on="on"
101+
style="margin-right: -6px;"
102+
>mdi-help-circle</v-icon>
103+
</template>
104+
<span>{{ item.description }}</span>
105+
</v-tooltip>
106+
</v-chip>
107+
</v-chip-group>
108+
109+
<v-data-table
110+
:items="env"
111+
:items-per-page="-1"
112+
class="elevation-1"
113+
hide-default-footer
114+
no-data-text="No values"
115+
>
116+
<template v-slot:item="props">
117+
<tr>
118+
<td class="pa-1">
119+
<v-text-field
120+
solo-inverted
121+
flat
122+
hide-details
123+
v-model="props.item.name"
124+
class="v-text-field--solo--no-min-height"
125+
></v-text-field>
126+
</td>
127+
<td class="pa-1">
128+
<v-text-field
129+
solo-inverted
130+
flat
131+
hide-details
132+
v-model="props.item.value"
133+
class="v-text-field--solo--no-min-height"
134+
></v-text-field>
135+
</td>
136+
<td style="width: 38px;">
137+
<v-icon
138+
small
139+
class="pa-1"
140+
@click="removeEnvVar(props.item)"
141+
>
142+
mdi-delete
143+
</v-icon>
144+
</td>
145+
</tr>
146+
</template>
147+
</v-data-table>
88148

149+
<div class="text-right mt-2 mb-4">
150+
<v-btn
151+
color="primary"
152+
@click="addEnvVar()"
153+
>New Variable</v-btn>
154+
</div>
89155
</div>
90156

91157
</v-form>
92158
</template>
159+
160+
<style lang="scss">
161+
.EnvironmentForm__predefinedEnvVars {
162+
.EnvironmentForm__predefinedEnvVarsValue {
163+
text-decoration: line-through;
164+
font-family: monospace;
165+
}
166+
.v-chip--active {
167+
.EnvironmentForm__predefinedEnvVarsValue {
168+
text-decoration: none;
169+
}
170+
}
171+
}
172+
</style>
173+
93174
<script>
94175
/* eslint-disable import/no-extraneous-dependencies,import/extensions */
95176
@@ -102,6 +183,12 @@ import 'codemirror/addon/display/placeholder.js';
102183
import EventBus from '@/event-bus';
103184
import { getErrorMessage } from '@/lib/error';
104185
186+
const PREDEFINED_ENV_VARS = [{
187+
name: 'ANSIBLE_HOST_KEY_CHECKING',
188+
value: 'False',
189+
description: 'Avoid host key checking by the tools Ansible uses to connect to the host.',
190+
}];
191+
105192
export default {
106193
mixins: [ItemFormBase],
107194
components: {
@@ -113,12 +200,13 @@ export default {
113200
114201
data() {
115202
return {
203+
PREDEFINED_ENV_VARS,
116204
images: [
117205
'dind-runner:latest',
118206
],
119207
advancedOptions: false,
120208
json: '{}',
121-
env: '{}',
209+
env: [],
122210
123211
cmOptions: {
124212
tabSize: 2,
@@ -128,10 +216,24 @@ export default {
128216
lint: true,
129217
indentWithTabs: false,
130218
},
219+
220+
extraVarsEditMode: 'json',
221+
predefinedEnvVars: [],
131222
};
132223
},
133224
134225
methods: {
226+
addEnvVar(name = '', value = '') {
227+
this.env.push({ name, value });
228+
},
229+
230+
removeEnvVar(val) {
231+
const i = this.env.findIndex((v) => v.name === val.name);
232+
if (i > -1) {
233+
this.env.splice(i, 1);
234+
}
235+
},
236+
135237
setExtraVar(name, value) {
136238
try {
137239
const obj = JSON.parse(this.json || '{}');
@@ -147,12 +249,41 @@ export default {
147249
148250
beforeSave() {
149251
this.item.json = this.json;
150-
this.item.env = this.env;
252+
253+
const env = (this.env || []).reduce((prev, curr) => ({
254+
...prev,
255+
[curr.name]: curr.value,
256+
}), {});
257+
258+
this.predefinedEnvVars.forEach((index) => {
259+
const predefinedVar = PREDEFINED_ENV_VARS[index];
260+
env[predefinedVar.name] = predefinedVar.value;
261+
});
262+
263+
this.item.env = JSON.stringify(env);
151264
},
152265
153266
afterLoadData() {
154267
this.json = this.item?.json || '{}';
155-
this.env = this.item?.env || '{}';
268+
269+
const env = JSON.parse(this.item?.env || '{}');
270+
271+
this.env = Object.keys(env)
272+
.filter((x) => {
273+
const index = PREDEFINED_ENV_VARS.findIndex((v) => v.name === x);
274+
return index === -1 || PREDEFINED_ENV_VARS[index].value !== env[x];
275+
})
276+
.map((x) => ({
277+
name: x,
278+
value: env[x],
279+
}));
280+
281+
Object.keys(env).forEach((x) => {
282+
const index = PREDEFINED_ENV_VARS.findIndex((v) => v.name === x);
283+
if (index !== -1 && PREDEFINED_ENV_VARS[index].value === env[x]) {
284+
this.predefinedEnvVars.push(index);
285+
}
286+
});
156287
},
157288
158289
getItemsUrl() {

web/src/components/ItemListPageBase.js

+3-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ObjectRefsDialog from '@/components/ObjectRefsDialog.vue';
66

77
import { getErrorMessage } from '@/lib/error';
88
import { USER_PERMISSIONS } from '@/lib/constants';
9+
import PermissionsCheck from '@/components/PermissionsCheck';
910

1011
export default {
1112
components: {
@@ -14,13 +15,13 @@ export default {
1415
ObjectRefsDialog,
1516
},
1617

18+
mixins: [PermissionsCheck],
19+
1720
props: {
1821
projectId: Number,
1922
projectType: String,
2023
userId: Number,
21-
userPermissions: Number,
2224
userRole: String,
23-
isAdmin: Boolean,
2425
user: Object,
2526
},
2627

@@ -54,14 +55,6 @@ export default {
5455
return this.can(USER_PERMISSIONS.manageProjectResources);
5556
},
5657

57-
can(permission) {
58-
if (this.isAdmin) {
59-
return true;
60-
}
61-
// eslint-disable-next-line no-bitwise
62-
return (this.userPermissions & permission) === permission;
63-
},
64-
6558
// eslint-disable-next-line no-empty-function
6659
async beforeLoadItems() {
6760
},
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export default {
2+
props: {
3+
userPermissions: Number,
4+
isAdmin: Boolean,
5+
},
6+
7+
methods: {
8+
9+
can(permission) {
10+
if (this.isAdmin) {
11+
return true;
12+
}
13+
// eslint-disable-next-line no-bitwise
14+
return (this.userPermissions & permission) === permission;
15+
},
16+
},
17+
};

web/src/views/project/TemplateView.vue

+4-3
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ import {
202202
import ObjectRefsDialog from '@/components/ObjectRefsDialog.vue';
203203
import NewTaskDialog from '@/components/NewTaskDialog.vue';
204204
import EditTemplateDialogue from '@/components/EditTemplateDialogue.vue';
205+
import PermissionsCheck from '@/components/PermissionsCheck';
205206
206207
export default {
207208
components: {
@@ -217,6 +218,8 @@ export default {
217218
userPermissions: Number,
218219
},
219220
221+
mixins: [PermissionsCheck],
222+
220223
data() {
221224
return {
222225
item: null,
@@ -238,9 +241,7 @@ export default {
238241
239242
computed: {
240243
canUpdate() {
241-
const perm = USER_PERMISSIONS.manageProjectResources;
242-
// eslint-disable-next-line no-bitwise
243-
return (this.userPermissions & perm) === perm;
244+
return this.can(USER_PERMISSIONS.manageProjectResources);
244245
},
245246
246247
viewId() {

0 commit comments

Comments
 (0)