Skip to content

Commit 836c6ae

Browse files
committed
adding missing files
1 parent 24f741c commit 836c6ae

34 files changed

+2257
-515
lines changed

webui/src/css/app.css

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,12 @@ h6:first-child {
403403
width: 75%;
404404
height: auto;
405405
max-height: 85vh;
406-
max-width: 800px;
406+
max-width: 850px;
407+
}
408+
409+
.wkt-center-text-in-frame {
410+
vertical-align: center;
411+
text-align: center;
407412
}
408413

409414
/* typically the oj-panel on the code view tab */
@@ -421,6 +426,11 @@ h6:first-child {
421426
height: 100%;
422427
}
423428

429+
.wkt-design-view-switcher {
430+
min-height: 1px;
431+
height: 100%;
432+
}
433+
424434
.wkt-wide-table {
425435
width: 100%;
426436
}

webui/src/js/models/image-definition.js

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@
1010
*
1111
* Returns a constructor for the object.
1212
*/
13-
define(['utils/observable-properties', 'utils/validation-helper'],
14-
function (props, validationHelper) {
13+
define(['knockout', 'utils/observable-properties', 'utils/validation-helper'],
14+
function (ko, props, validationHelper) {
1515
/**
1616
* The object constructor.
1717
*/
1818
return function (name, wdtModel) {
1919
function ImageModel() {
2020
this.imageTag = props.createProperty();
2121
this.imageTag.addValidator(...validationHelper.getImageTagValidators());
22-
this.createCustomImageForPV = props.createProperty(true);
22+
this.createPrimaryImage = props.createProperty(false);
23+
24+
// deprecated and no longer used as of version 1.1.0
25+
this.createCustomImageForPV = props.createProperty(false);
2326

2427
this.imageRegistryPushRequireAuthentication = props.createProperty(true);
2528
this.imageRegistryPushUser = props.createProperty().asCredential();
@@ -56,19 +59,56 @@ define(['utils/observable-properties', 'utils/validation-helper'],
5659
this.targetDomainType = props.createProperty('WLS');
5760
this.domainHomePath = props.createProperty('/u01/domains/${1}', wdtModel.domainName);
5861
this.modelHomePath = props.createProperty('/u01/wdt/models');
62+
this.wdtHomePath = props.createProperty('/u01/wdt');
63+
64+
this.targetOpenShift = props.createProperty(false);
65+
this.defaultGroupName = ko.computed(() => {
66+
return this.targetOpenShift.value ? 'root' : 'oracle';
67+
});
5968

6069
this.fileOwner = props.createProperty('oracle');
61-
this.fileGroup = props.createProperty('oracle');
70+
this.fileGroup = props.createProperty('${1}', this.defaultGroupName);
6271
this.alwaysPullBaseImage = props.createProperty(false);
6372
this.builderNetworkName = props.createProperty();
64-
6573
this.extendBuild = props.createProperty(false);
6674
this.additionalBuildCommandsFile = props.createProperty();
6775
this.additionalBuildFiles = props.createArrayProperty([]);
6876

77+
// aux image versions of the variables
78+
this.useAuxImage = props.createProperty(true);
79+
this.auxImageTag = props.createProperty();
80+
this.auxImageTag.addValidator(...validationHelper.getImageTagValidators());
81+
this.createAuxImage = props.createProperty(true);
82+
83+
this.auxImageRegistryPushRequireAuthentication = props.createProperty(true);
84+
this.auxImageRegistryPushUser = props.createProperty().asCredential();
85+
this.auxImageRegistryPushPassword = props.createProperty().asCredential();
86+
87+
this.auxUseCustomBaseImage = props.createProperty(false);
88+
this.auxBaseImage = props.createProperty();
89+
this.auxBaseImage.addValidator(...validationHelper.getImageTagValidators());
90+
this.auxBaseImagePullRequiresAuthentication = props.createProperty(false);
91+
this.auxBaseImagePullUsername = props.createProperty().asCredential();
92+
this.auxBaseImagePullPassword = props.createProperty().asCredential();
93+
94+
this.auxTargetOpenShift = props.createProperty(false);
95+
this.auxDefaultGroupName = ko.computed(() => {
96+
return this.auxTargetOpenShift.value ? 'root' : 'oracle';
97+
});
98+
99+
this.auxFileOwner = props.createProperty('oracle');
100+
this.auxFileGroup = props.createProperty('${1}', this.auxDefaultGroupName);
101+
this.auxAlwaysPullBaseImage = props.createProperty(false);
102+
this.auxBuilderNetworkName = props.createProperty();
103+
this.auxExtendBuild = props.createProperty(false);
104+
this.auxAdditionalBuildCommandsFile = props.createProperty();
105+
this.auxAdditionalBuildFiles = props.createArrayProperty([]);
106+
69107
// internal fields that should not be read or written to the project file.
70108
this.internal = {
109+
auxImageRegistryAddress: props.createProperty(),
71110
imageRegistryAddress: props.createProperty(),
111+
auxBaseImageRegistryAddress: props.createProperty(),
72112
baseImageRegistryAddress: props.createProperty()
73113
};
74114

@@ -81,6 +121,14 @@ define(['utils/observable-properties', 'utils/validation-helper'],
81121
this.internal.imageRegistryAddress.observable(host);
82122
});
83123

124+
this.auxImageTag.observable.subscribe(value => {
125+
let host;
126+
if (value && value.length > 0) {
127+
host = window.api.k8s.getRegistryAddressFromImageTag(value);
128+
}
129+
this.internal.auxImageRegistryAddress.observable(host);
130+
});
131+
84132
this.baseImage.observable.subscribe(value => {
85133
let host;
86134
if (value && value.length > 0) {
@@ -89,6 +137,14 @@ define(['utils/observable-properties', 'utils/validation-helper'],
89137
this.internal.baseImageRegistryAddress.observable(host);
90138
});
91139

140+
this.auxBaseImage.observable.subscribe(value => {
141+
let host;
142+
if (value && value.length > 0) {
143+
host = window.api.k8s.getRegistryAddressFromImageTag(value);
144+
}
145+
this.internal.auxBaseImageRegistryAddress.observable(host);
146+
});
147+
92148
this.readFrom = (json) => {
93149
props.createGroup(name, this).readFrom(json);
94150
};

webui/src/js/models/k8s-domain-definition.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
define(['knockout', 'utils/observable-properties', 'utils/common-utilities', 'utils/validation-helper', 'utils/wkt-logger'],
1414
function (ko, props, utils, validationHelper, wktLogger) {
1515

16-
return function(name, wdtModel, imageDomainHomePathProperty) {
16+
return function(name, wdtModel, imageDomainHomePathProperty, imageDomainTypeProperty) {
1717
function asLegalK8sName(observable) {
1818
return utils.toLegalK8sName(observable());
1919
}
@@ -25,6 +25,7 @@ define(['knockout', 'utils/observable-properties', 'utils/common-utilities', 'ut
2525
this.kubernetesNamespace = props.createProperty('${1}-ns', this.uid.observable);
2626
this.kubernetesNamespace.addValidator(...validationHelper.getK8sNameValidators());
2727
this.domainHome = imageDomainHomePathProperty;
28+
this.domainType = imageDomainTypeProperty;
2829

2930
this.domainPersistentVolumeName = props.createProperty('weblogic-domain-storage-volume');
3031
this.domainPersistentVolumeMountPath = props.createProperty('/shared');
@@ -45,6 +46,17 @@ define(['knockout', 'utils/observable-properties', 'utils/common-utilities', 'ut
4546

4647
this.imagePullPolicy = props.createProperty('IfNotPresent');
4748

49+
// Auxiliary image-related properties
50+
this.auxImageRegistryPullRequireAuthentication = props.createProperty(false);
51+
this.auxImageRegistryUseExistingPullSecret = props.createProperty(true);
52+
this.auxImageRegistryPullSecretName = props.createProperty();
53+
this.auxImageRegistryPullSecretName.addValidator(...validationHelper.getK8sNameValidators());
54+
this.auxImageRegistryPullUser = props.createProperty().asCredential();
55+
this.auxImageRegistryPullPassword = props.createProperty().asCredential();
56+
this.auxImageRegistryPullEmail = props.createProperty();
57+
this.auxImageRegistryPullEmail.addValidator(...validationHelper.getEmailAddressValidators());
58+
this.auxImagePullPolicy = props.createProperty('IfNotPresent');
59+
4860
this.clusterKeys = [
4961
'name', 'maxServers', 'replicas', 'minHeap', 'maxHeap', 'cpuRequest', 'cpuLimit', 'memoryRequest',
5062
'memoryLimit', 'disableDebugStdout', 'disableFan', 'useUrandom', 'additionalArguments'

webui/src/js/models/wkt-project.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function (ko, wdtConstructor, imageConstructor, kubectlConstructor, domainConstr
7777
this.image = imageConstructor('image', this.wdtModel);
7878
this.ingress = ingressConstructor('ingress');
7979
this.kubectl = kubectlConstructor('kubectl');
80-
this.k8sDomain = domainConstructor('k8sDomain', this.wdtModel, this.image.domainHomePath);
80+
this.k8sDomain = domainConstructor('k8sDomain', this.wdtModel, this.image.domainHomePath, this.image.targetDomainType);
8181
this.wko = wkoConstructor('wko');
8282
this.pages = [this.wdtModel, this.image, this.kubectl, this.k8sDomain, this.wko, this.settings, this.ingress];
8383

webui/src/js/utils/image-pusher.js

Lines changed: 156 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,23 @@ define(['models/wkt-project', 'models/wkt-console', 'utils/i18n', 'utils/project
1414
return this.callPushImage();
1515
};
1616

17+
this.startPushAuxImage = async () => {
18+
return this.callPushAuxImage();
19+
};
20+
1721
this.callPushImage = async (options) => {
1822
if (!options) {
1923
options = {};
2024
}
2125

2226
let errTitle = i18n.t('image-pusher-push-aborted-title');
23-
if (this.project.settings.targetDomainLocation.value === 'pv' && !this.project.image.createCustomImageForPV.value) {
24-
const errMessage = i18n.t('image-pusher-domain-location-pv-message');
27+
if (!this.project.image.createPrimaryImage.value) {
28+
const errMessage = i18n.t('image-pusher-image-not-create-message');
2529
await window.api.ipc.invoke('show-info-message', errTitle, errMessage);
2630
return Promise.resolve(false);
2731
}
2832

29-
const validatableObject = this.getValidatableObject('flow-push-image-name');
33+
const validatableObject = this.getValidatableObjectForPrimary('flow-push-image-name');
3034
if (validatableObject.hasValidationErrors()) {
3135
const validationErrorDialogConfig = validatableObject.getValidationErrorDialogConfig(errTitle);
3236
dialogHelper.openDialog('validation-error-dialog', validationErrorDialogConfig);
@@ -117,29 +121,168 @@ define(['models/wkt-project', 'models/wkt-console', 'utils/i18n', 'utils/project
117121
}
118122
};
119123

120-
this.getValidatableObject = (flowNameKey) => {
124+
this.getValidatableObjectForPrimary = (flowNameKey) => {
121125
const validationObject = validationHelper.createValidatableObject(flowNameKey);
122-
const settingsFormConfig = validationObject.getDefaultConfigObject();
123-
settingsFormConfig.formName = 'project-settings-title';
126+
const imageFormConfig = validationObject.getDefaultConfigObject();
127+
imageFormConfig.formName = 'image-design-form-name';
128+
imageFormConfig.tabName = 'image-design-form-primary-tab-name';
124129

125130
validationObject.addField('image-design-image-tag-label',
126-
this.project.image.imageTag.validate(true), settingsFormConfig);
131+
this.project.image.imageTag.validate(true), imageFormConfig);
127132

128-
const settingsFormBuilderConfig = validationObject.getDefaultConfigObject();
129-
settingsFormBuilderConfig.formName = 'project-settings-title';
130-
settingsFormBuilderConfig.fieldNamePayload = { toolName: this.project.settings.builderType.value };
133+
const settingsFormConfig = validationObject.getDefaultConfigObject();
134+
settingsFormConfig.formName = 'project-settings-title';
135+
settingsFormConfig.fieldNamePayload = { toolName: this.project.settings.builderType.value };
131136
validationObject.addField('project-settings-build-tool-label',
132137
validationHelper.validateRequiredField(this.project.settings.builderExecutableFilePath.value),
133-
settingsFormBuilderConfig);
138+
settingsFormConfig);
134139

135140
if (this.project.image.imageRegistryPushRequireAuthentication.value) {
136141
// skip validating the host portion of the image tag since it may be empty for Docker Hub...
137142
validationObject.addField('image-design-image-registry-push-username-label',
138143
validationHelper.validateRequiredField(this.project.image.imageRegistryPushUser.value),
139-
settingsFormConfig);
144+
imageFormConfig);
140145
validationObject.addField('image-design-image-registry-push-password-label',
141146
validationHelper.validateRequiredField(this.project.image.imageRegistryPushPassword.value),
142-
settingsFormConfig);
147+
imageFormConfig);
148+
}
149+
150+
return validationObject;
151+
};
152+
153+
this.callPushAuxImage = async (options) => {
154+
if (!options) {
155+
options = {};
156+
}
157+
158+
let errTitle = i18n.t('image-pusher-push-aborted-title');
159+
let abortErrorMessage;
160+
if (this.project.settings.targetDomainLocation.value !== 'mii') {
161+
abortErrorMessage = i18n.t('image-pusher-aux-image-not-mii-message');
162+
} else if (!this.project.image.useAuxImage.value) {
163+
abortErrorMessage = i18n.t('image-pusher-aux-image-not-use-message');
164+
} else if (!this.project.image.createAuxImage.value) {
165+
abortErrorMessage = i18n.t('image-pusher-aux-image-not-create-message');
166+
}
167+
if (abortErrorMessage) {
168+
await window.api.ipc.invoke('show-info-message', errTitle, abortErrorMessage);
169+
return Promise.resolve(false);
170+
}
171+
172+
173+
const validatableObject = this.getValidatableObjectForAux('flow-push-aux-image-name');
174+
if (validatableObject.hasValidationErrors()) {
175+
const validationErrorDialogConfig = validatableObject.getValidationErrorDialogConfig(errTitle);
176+
dialogHelper.openDialog('validation-error-dialog', validationErrorDialogConfig);
177+
return Promise.resolve(false);
178+
}
179+
180+
const totalSteps = 4.0;
181+
const imageTag = this.project.image.auxImageTag.value;
182+
183+
let busyDialogMessage = i18n.t('flow-image-builder-validation-in-progress', {imageTag: imageTag});
184+
dialogHelper.openBusyDialog(busyDialogMessage, 'bar');
185+
dialogHelper.updateBusyDialog(busyDialogMessage, 0/totalSteps);
186+
try {
187+
const imageBuilderExe = this.project.settings.builderExecutableFilePath.value;
188+
if (!options.skipImageBuilderValidation) {
189+
const imageBuilderExeResults =
190+
await window.api.ipc.invoke('validate-image-builder-exe', imageBuilderExe);
191+
if (!imageBuilderExeResults.isValid) {
192+
const errMessage = i18n.t('image-pusher-image-builder-invalid-error-message',
193+
{fileName: imageBuilderExe, error: imageBuilderExeResults.reason});
194+
await window.api.ipc.invoke('show-error-message', errTitle, errMessage);
195+
return Promise.resolve(false);
196+
}
197+
}
198+
199+
busyDialogMessage = i18n.t('image-pusher-image-exists-in-progress', {imageTag: imageTag});
200+
dialogHelper.updateBusyDialog(busyDialogMessage, 1/totalSteps);
201+
if (!options.skipLocalImageExistsValidation) {
202+
const imageExistsResults =
203+
await window.api.ipc.invoke('validate-image-exists-locally', imageBuilderExe, imageTag);
204+
let errMessage;
205+
if (imageExistsResults.isSuccess && !imageExistsResults.imageExists) {
206+
errMessage = i18n.t('image-pusher-image-not-exists-error-message', {imageTag: imageTag});
207+
} else if (!imageExistsResults.isSuccess) {
208+
errMessage = i18n.t('image-pusher-image-exists-failed-error-message',
209+
{imageTag: imageTag, error: imageExistsResults.reason});
210+
}
211+
if (errMessage) {
212+
await window.api.ipc.invoke('show-error-message', errTitle, errMessage);
213+
return Promise.resolve(false);
214+
}
215+
}
216+
217+
busyDialogMessage = i18n.t('flow-save-project-in-progress');
218+
dialogHelper.updateBusyDialog(busyDialogMessage, 2/totalSteps);
219+
if (!options.skipProjectSave) {
220+
const saveResult = await projectIo.saveProject();
221+
if (!saveResult.saved) {
222+
const errMessage = `${i18n.t('image-pusher-project-not-saved-error-prefix')}: ${saveResult.reason}`;
223+
await window.api.ipc.invoke('show-error-message', errTitle, errMessage);
224+
return Promise.resolve(false);
225+
}
226+
}
227+
228+
if (!options.skipClearAndShowConsole) {
229+
wktConsole.clear();
230+
wktConsole.show(true);
231+
}
232+
233+
busyDialogMessage = i18n.t('image-pusher-push-in-progress', {imageTag: imageTag});
234+
dialogHelper.updateBusyDialog(busyDialogMessage, 3/totalSteps);
235+
const pushOptions = {
236+
requiresLogin: this.project.image.auxImageRegistryPushRequireAuthentication.value,
237+
host: this.project.image.internal.auxImageRegistryAddress.value,
238+
username: this.project.image.auxImageRegistryPushUser.value,
239+
password: this.project.image.auxImageRegistryPushPassword.value
240+
};
241+
let pushResults = await window.api.ipc.invoke('do-push-image', imageBuilderExe, imageTag, pushOptions);
242+
dialogHelper.closeBusyDialog();
243+
if (pushResults.isSuccess) {
244+
if (!options.skipCompleteDialog) {
245+
const title = i18n.t('image-pusher-create-complete-title');
246+
const message = i18n.t('image-pusher-create-complete-message', {imageTag: imageTag});
247+
await window.api.ipc.invoke('show-info-message', title, message);
248+
}
249+
return Promise.resolve(true);
250+
} else {
251+
const failedTitle = i18n.t('image-pusher-push-failed-title');
252+
const failedMessage = i18n.t('image-pusher-push-failed-error-message', {error: pushResults.reason});
253+
await window.api.ipc.invoke('show-error-message', failedTitle, failedMessage);
254+
return Promise.resolve(false);
255+
}
256+
} catch (err) {
257+
dialogHelper.closeBusyDialog();
258+
throw err;
259+
} finally {
260+
dialogHelper.closeBusyDialog();
261+
}
262+
};
263+
264+
this.getValidatableObjectForAux = (flowNameKey) => {
265+
const validationObject = validationHelper.createValidatableObject(flowNameKey);
266+
const imageFormConfig = validationObject.getDefaultConfigObject();
267+
imageFormConfig.formName = 'image-design-form-name';
268+
imageFormConfig.tabName = 'image-design-form-auxiliary-tab-name';
269+
270+
validationObject.addField('image-design-image-tag-label',
271+
this.project.image.auxImageTag.validate(true), imageFormConfig);
272+
273+
const settingsFormConfig = validationObject.getDefaultConfigObject();
274+
settingsFormConfig.formName = 'project-settings-form-name';
275+
settingsFormConfig.fieldNamePayload = { toolName: this.project.settings.builderType.value };
276+
validationObject.addField('project-settings-build-tool-label',
277+
validationHelper.validateRequiredField(this.project.settings.builderExecutableFilePath.value),
278+
settingsFormConfig);
279+
280+
if (this.project.image.auxImageRegistryPushRequireAuthentication.value) {
281+
// skip validating the host portion of the image tag since it may be empty for Docker Hub...
282+
validationObject.addField('image-design-aux-image-registry-push-username-label',
283+
validationHelper.validateRequiredField(this.project.image.auxImageRegistryPushUser.value), imageFormConfig);
284+
validationObject.addField('image-design-aux-image-registry-push-password-label',
285+
validationHelper.validateRequiredField(this.project.image.auxImageRegistryPushPassword.value), imageFormConfig);
143286
}
144287

145288
return validationObject;

0 commit comments

Comments
 (0)