Skip to content

Commit 11b3973

Browse files
Wdt-1112 Handle application folder directories that contain app and plan directories (#1149)
* copy correct location into plan.xml * remote paths fixed * fix non-remote names
1 parent db5e0cf commit 11b3973

File tree

6 files changed

+222
-14
lines changed

6 files changed

+222
-14
lines changed

core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ public class WLSDeployArchive {
5858
*/
5959
public static final String ARCHIVE_APPS_TARGET_DIR = WLSDPLY_ARCHIVE_BINARY_DIR + "/applications";
6060

61+
/**
62+
* Top-level archive subdirectory where the applications are stored and the subdirectory to which
63+
* they will be extracted. This is for structured applications found under /app
64+
*/
65+
public static final String ARCHIVE_STRUCT_APPS_TARGET_DIR = WLSDPLY_ARCHIVE_BINARY_DIR + "/structuredApplications";
66+
6167
/**
6268
* Top-level archive subdirectory where the shared libraries are stored and the subdirectory to
6369
* which they will be extracted.
@@ -573,6 +579,17 @@ public String getApplicationArchivePath(String appPath) {
573579
return getArchiveName(ARCHIVE_APPS_TARGET_DIR, appPath);
574580
}
575581

582+
/**
583+
* Get the archive path for the application in a well-formed application directory
584+
* @param appPath name of the application path
585+
* @return archive path for use in the model
586+
*/
587+
public String getApplicationDirectoryArchivePath(String appName, String appPath) {
588+
File zipAppPath = new File(appPath).getParentFile();
589+
File zipAppFile = new File(appPath);
590+
return ARCHIVE_STRUCT_APPS_TARGET_DIR + "/" + appName + "/" + zipAppPath.getName() + "/" + zipAppFile.getName();
591+
}
592+
576593
/**
577594
* This method adds an application to the archive. If an application with the same name already exists, this
578595
* method assumes that the new one also needs to be added so it changes the name to prevent conflicts by adding
@@ -590,13 +607,40 @@ public String addApplication(String appPath) throws WLSDeployArchiveIOException
590607
LOGGER.entering(CLASS, METHOD, appPath);
591608

592609
File filePath = new File(appPath);
610+
593611
validateExistingFile(filePath, "appPath", getArchiveFileName(), METHOD, true);
594612

595613
String newName = addItemToZip(ARCHIVE_APPS_TARGET_DIR, filePath);
596614
LOGGER.exiting(CLASS, METHOD, newName);
597615
return newName;
598616
}
599617

618+
public String addApplicationFolder(String appName, String appPath)
619+
throws WLSDeployArchiveIOException {
620+
final String METHOD = "addApplicationFolder";
621+
LOGGER.entering(CLASS, METHOD, appName, appPath);
622+
File zipPath = new File(appPath);
623+
if (zipPath.getParentFile() != null) {
624+
zipPath = zipPath.getParentFile();
625+
}
626+
String firstPrefix = ARCHIVE_STRUCT_APPS_TARGET_DIR + "/" + appName + "/" + zipPath.getName();
627+
String newName = walkDownFolders(firstPrefix, zipPath);
628+
LOGGER.exiting(CLASS, METHOD, newName);
629+
return newName;
630+
}
631+
632+
public String addApplicationPlanFolder(String appName, String planDir)
633+
throws WLSDeployArchiveIOException {
634+
final String METHOD = "addApplicationPathFolder";
635+
LOGGER.entering(CLASS, METHOD, appName, planDir);
636+
File zipPlan = new File(planDir);
637+
String zipPrefix = ARCHIVE_STRUCT_APPS_TARGET_DIR + "/" + appName + "/" + zipPlan.getName();
638+
String newName = walkDownFolders(zipPrefix, zipPlan);
639+
640+
LOGGER.exiting(CLASS, METHOD, newName);
641+
return zipPrefix;
642+
}
643+
600644
/**
601645
* Get the list of application names in the archive.
602646
*
@@ -671,11 +715,13 @@ public void extractApplication(String applicationPath, File domainHome) throws W
671715
validateExistingDirectory(domainHome, "domainHome", getArchiveFileName(), METHOD);
672716

673717
String appPath = applicationPath;
674-
if (!applicationPath.startsWith(ARCHIVE_APPS_TARGET_DIR)) {
718+
if (!applicationPath.startsWith(ARCHIVE_STRUCT_APPS_TARGET_DIR) &&
719+
!applicationPath.startsWith(ARCHIVE_APPS_TARGET_DIR)) {
675720
appPath = ARCHIVE_APPS_TARGET_DIR + ZIP_SEP + applicationPath;
676721
}
677722
extractFileFromZip(appPath, domainHome);
678723
LOGGER.exiting(CLASS, METHOD);
724+
679725
}
680726

681727
/**
@@ -1007,6 +1053,18 @@ public String getApplicationPlanArchivePath(String planFile) {
10071053
return getArchiveName(ARCHIVE_APPS_TARGET_DIR, planFile);
10081054
}
10091055

1056+
/**
1057+
* Get the archive path of a well formed plan directory in app directory,
1058+
*
1059+
* @param appName The application name of the app directory
1060+
* @param planDir The deployment plan file directory
1061+
* @return Archive path for use in the model
1062+
*/
1063+
public String getApplicationPlanDirArchivePath(String appName, String planDir) {
1064+
File zipPath = new File(planDir);
1065+
return ARCHIVE_STRUCT_APPS_TARGET_DIR + "/" + appName + "/" + zipPath.getName();
1066+
}
1067+
10101068
/**
10111069
* Adds an application's deployment plan file to the archive.
10121070
*
@@ -1441,7 +1499,6 @@ protected String addItemToZip(String zipPathPrefix, File itemToAdd, boolean useF
14411499

14421500
LOGGER.entering(CLASS, METHOD, zipPathPrefix, itemToAdd.getAbsolutePath(), useFileNameInEntryPath);
14431501
String newName = getArchiveName(zipPathPrefix, itemToAdd.getName(), useFileNameInEntryPath);
1444-
14451502
if (itemToAdd.isDirectory()) {
14461503
if (!newName.endsWith(ZIP_SEP)) {
14471504
newName += ZIP_SEP;
@@ -1819,4 +1876,20 @@ private static FileInputStream getFileInputStream(File f, String itemName, Strin
18191876
return inputStream;
18201877
}
18211878

1879+
private String walkDownFolders(String zipPrefix, File zipPath) throws WLSDeployArchiveIOException {
1880+
String newSourceName = null;
1881+
if (zipPath != null) {
1882+
File[] fileList = zipPath.listFiles();
1883+
if (fileList != null) {
1884+
for (File item : fileList) {
1885+
newSourceName = addItemToZip(zipPrefix, item);
1886+
if (item.isDirectory()) {
1887+
walkDownFolders(zipPrefix + "/" + item.getName(), item);
1888+
}
1889+
}
1890+
}
1891+
}
1892+
return newSourceName;
1893+
}
1894+
18221895
}

core/src/main/java/oracle/weblogic/deploy/util/XPathUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public XPathUtil(String oracleHome){
3939
}
4040

4141
public XPathUtil() {
42-
// for testing only
42+
// for use by other types of docs
4343
}
4444

4545
private static XPathFactory factory = null;

core/src/main/python/wlsdeploy/tool/deploy/applications_deployer.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,18 @@
99
import os
1010
from java.io import File
1111
from java.io import IOException
12+
from java.io import FileOutputStream
1213
from java.security import NoSuchAlgorithmException
14+
from javax.xml.parsers import DocumentBuilderFactory
15+
from javax.xml.transform import OutputKeys
16+
from javax.xml.transform import TransformerFactory
17+
from javax.xml.transform.dom import DOMSource
18+
from javax.xml.transform.stream import StreamResult
1319

1420
import oracle.weblogic.deploy.util.FileUtils as FileUtils
1521
import oracle.weblogic.deploy.util.PyOrderedDict as OrderedDict
22+
from oracle.weblogic.deploy.util import WLSDeployArchive
23+
1624
from wlsdeploy.aliases import alias_utils
1725
from wlsdeploy.aliases import model_constants
1826
from wlsdeploy.aliases.location_context import LocationContext
@@ -21,6 +29,7 @@
2129
from wlsdeploy.aliases.model_constants import DEPLOYMENT_ORDER
2230
from wlsdeploy.aliases.model_constants import LIBRARY
2331
from wlsdeploy.aliases.model_constants import PARTITION
32+
from wlsdeploy.aliases.model_constants import PLAN_DIR
2433
from wlsdeploy.aliases.model_constants import PLAN_PATH
2534
from wlsdeploy.aliases.model_constants import PLAN_STAGING_MODE
2635
from wlsdeploy.aliases.model_constants import RESOURCES
@@ -183,6 +192,7 @@ def __add_applications(self):
183192
self.logger.throwing(ex, class_name=self._class_name, method_name=_method_name)
184193
raise ex
185194

195+
186196
application_name = \
187197
self.version_helper.get_application_versioned_name(app_source_path, application_name)
188198

@@ -193,6 +203,11 @@ def __add_applications(self):
193203
deployer_utils.create_and_cd(application_location, existing_applications, self.aliases)
194204
self._set_attributes_and_add_subfolders(application_location, application)
195205
application_location.remove_name_token(application_token)
206+
207+
if app_source_path.startswith(WLSDeployArchive.ARCHIVE_STRUCT_APPS_TARGET_DIR):
208+
plan_dir = dictionary_utils.get_element(application, PLAN_DIR)
209+
self._fix_plan_file(plan_dir)
210+
196211
self.logger.exiting(class_name=self._class_name, method_name=_method_name)
197212

198213
def __online_deploy_apps_and_libs(self, base_location):
@@ -629,6 +644,10 @@ def __build_app_deploy_strategy(self, location, model_apps, existing_app_refs, s
629644
if param in app_dict:
630645
self.model_context.replace_tokens(APPLICATION, app, param, app_dict)
631646

647+
if param == SOURCE_PATH and param.startswith(WLSDeployArchive.ARCHIVE_STRUCT_APPS_TARGET_DIR):
648+
plan_dir = dictionary_utils.get_element(app, PLAN_DIR)
649+
self._fix_plan_file(plan_dir)
650+
632651
if model_helper.is_delete_name(app):
633652
if self.__verify_delete_versioned_app(app, existing_apps, 'app'):
634653
# remove the !app from the model
@@ -949,7 +968,6 @@ def __deploy_model_applications(self, model_apps, app_location, deployed_applist
949968
path = app_dict[uses_path_tokens_attribute_name]
950969
if deployer_utils.is_path_into_archive(path):
951970
self.__extract_source_path_from_archive(path, APPLICATION, app_name)
952-
953971
location.add_name_token(token_name, app_name)
954972
resource_group_template_name, resource_group_name, partition_name = \
955973
self.__get_mt_names_from_location(location)
@@ -1121,6 +1139,29 @@ def __get_deployment_ordering(self, apps):
11211139
class_name=self._class_name, method_name=_method_name)
11221140
return result_deploy_order
11231141

1142+
def _fix_plan_file(self, plan_dir):
1143+
#self.archive_helper.extract_directory(plan_dir)
1144+
plan_file = os.path.join(self.model_context.get_domain_home(), plan_dir, "plan.xml")
1145+
dbf = DocumentBuilderFactory.newInstance()
1146+
db = dbf.newDocumentBuilder()
1147+
document = db.parse(File(plan_file))
1148+
document.normalizeDocument()
1149+
elements = document.getElementsByTagName("config-root")
1150+
1151+
if elements is not None and elements.getLength() > 0:
1152+
element = elements.item(0)
1153+
element.setNodeValue(plan_dir)
1154+
element.setTextContent(plan_dir)
1155+
ostream = FileOutputStream(plan_file)
1156+
transformer_factory = TransformerFactory.newInstance()
1157+
transformer = transformer_factory.newTransformer()
1158+
transformer.setOutputProperty(OutputKeys.INDENT, "yes")
1159+
transformer.setOutputProperty(OutputKeys.STANDALONE, "no")
1160+
source = DOMSource(document)
1161+
result = StreamResult(ostream)
1162+
1163+
transformer.transform(source, result)
1164+
11241165
def __start_all_apps(self, deployed_app_list, base_location):
11251166

11261167
temp_app_dict = OrderedDict()

core/src/main/python/wlsdeploy/tool/discover/deployments_discoverer.py

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Copyright (c) 2017, 2020, Oracle Corporation and/or its affiliates. All rights reserved.
33
Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
44
"""
5+
import os
6+
57
from java.io import File
68
from java.lang import IllegalArgumentException
79

@@ -241,6 +243,10 @@ def _add_application_to_archive(self, application_name, application_dict):
241243
_logger.entering(application_name, class_name=_class_name, method_name=_method_name)
242244
archive_file = self._model_context.get_archive_file()
243245
if model_constants.SOURCE_PATH in application_dict:
246+
if model_constants.PLAN_DIR in application_dict and \
247+
self._test_app_folder(application_dict[model_constants.SOURCE_PATH],
248+
application_dict[model_constants.PLAN_DIR]):
249+
return self._create_app_folder(application_name, application_dict)
244250
file_name = application_dict[model_constants.SOURCE_PATH]
245251
if file_name:
246252
file_name_path = file_name
@@ -260,14 +266,7 @@ def _add_application_to_archive(self, application_name, application_dict):
260266
try:
261267
new_source_name = archive_file.addApplication(file_name_path)
262268
except IllegalArgumentException, iae:
263-
if model_constants.TARGET in application_dict:
264-
target = application_dict[model_constants.TARGET]
265-
del application_dict[model_constants.TARGET]
266-
_logger.warning('WLSDPLY-06395', application_name, target, iae.getLocalizedMessage(),
267-
class_name=_class_name, method_name=_method_name)
268-
else:
269-
_logger.warning('WLSDPLY-06396', application_name, iae.getLocalizedMessage(),
270-
class_name=_class_name, method_name=_method_name)
269+
self._disconnect_target(application_name, application_dict, iae.getLocalizedMessage())
271270
except WLSDeployArchiveIOException, wioe:
272271
de = exception_helper.create_discover_exception('WLSDPLY-06397', application_name,
273272
file_name_path, wioe.getLocalizedMessage())
@@ -310,14 +309,107 @@ def add_application_plan_to_archive(self, application_name, application_dict):
310309
_logger.exiting(class_name=_class_name, method_name=_method_name)
311310
return
312311

312+
def _create_app_folder(self, application_name, application_dict):
313+
"""
314+
Create a well-formed application and plan directory
315+
:param application_name: name of application
316+
:param application_dict: model dictionary with application parameters
317+
:return: newly constructed source name
318+
"""
319+
_method_name = '_create_app_folder'
320+
321+
_logger.entering(application_name, class_name=_class_name, method_name=_method_name)
322+
323+
self._create_application_directory(application_name, application_dict)
324+
self._create_plan_directory(application_name, application_dict)
325+
326+
_logger.exiting(class_name=_class_name, method_name=_method_name)
327+
328+
def _test_app_folder(self, source_path, plan_dir):
329+
app_folder = False
330+
app_dir = File(source_path).getParent()
331+
if app_dir.endswith('app') and plan_dir.endswith('plan'):
332+
app_folder = True
333+
return app_folder
334+
335+
def _disconnect_target(self, application_name, application_dict, message):
336+
_method_name = '_disconnect_target'
337+
if model_constants.TARGET in application_dict:
338+
target = application_dict[model_constants.TARGET]
339+
del application_dict[model_constants.TARGET]
340+
_logger.warning('WLSDPLY-06395', application_name, target, message,
341+
class_name=_class_name, method_name=_method_name)
342+
else:
343+
_logger.warning('WLSDPLY-06396', application_name, iae.getLocalizedMessage(),
344+
class_name=_class_name, method_name=_method_name)
345+
def _create_application_directory(self, application_name, application_dict):
346+
_method_name = '_create_application_directory'
347+
new_source_name = None
348+
app_dir = application_dict[model_constants.SOURCE_PATH]
349+
archive_file = self._model_context.get_archive_file()
350+
if self._model_context.is_remote():
351+
new_source_name = archive_file.getApplicationDirectoryArchivePath(application_name, app_dir)
352+
353+
self.add_to_remote_map(app_dir, new_source_name,
354+
WLSDeployArchive.ArchiveEntryType.APPLICATIONS.name())
355+
elif not self._model_context.skip_archive():
356+
if not os.path.abspath(app_dir):
357+
app_dir = os.path.join(self._model_context.get_domain_home(), app_dir)
358+
try:
359+
new_source_name = archive_file.addApplicationFolder(application_name, app_dir)
360+
except IllegalArgumentException, iae:
361+
self._disconnect_target(application_name, application_dict, iae.getLocalizedMessage())
362+
except WLSDeployArchiveIOException, wioe:
363+
de = exception_helper.create_discover_exception('WLSDPLY-06403', application_name,
364+
file_name_path, wioe.getLocalizedMessage())
365+
_logger.throwing(class_name=_class_name, method_name=_method_name, error=de)
366+
raise de
367+
if new_source_name is not None:
368+
_logger.finer('WLSDPLY-06398', application_name, new_source_name, class_name=_class_name,
369+
method_name=_method_name)
370+
application_dict[model_constants.SOURCE_PATH] = new_source_name
371+
372+
def _create_plan_directory(self, application_name, application_dict):
373+
_method_name = '_create_plan_directory'
374+
new_source_name = None
375+
plan_dir = application_dict[model_constants.PLAN_DIR]
376+
archive_file = self._model_context.get_archive_file()
377+
if not os.path.abspath(plan_dir):
378+
plan_dir = os.path.join(self._model_context.get_domain_home(), plan_dir)
379+
if self._model_context.is_remote():
380+
new_source_name = archive_file.getApplicationPlanDirArchivePath(application_name, plan_dir)
381+
self.add_to_remote_map(plan_dir, new_source_name,
382+
WLSDeployArchive.ArchiveEntryType.APPLICATION_PLAN.name())
383+
elif not self._model_context.skip_archive():
384+
try:
385+
new_source_name = archive_file.addApplicationPlanFolder(application_name, plan_dir)
386+
except IllegalArgumentException, iae:
387+
_logger.warning('WLSDPLY-06395', application_name, plan_dir,
388+
iae.getLocalizedMessage(), class_name=_class_name,
389+
method_name=_method_name)
390+
new_source_name = None
391+
except WLSDeployArchiveIOException, wioe:
392+
de = exception_helper.create_discover_exception('WLSDPLY-06397', application_dict, plan_dir,
393+
wioe.getLocalizedMessage())
394+
_logger.throwing(class_name=_class_name, method_name=_method_name, error=de)
395+
raise de
396+
if new_source_name is not None:
397+
_logger.finer('WLSDPLY-06398', application_name, new_source_name, class_name=_class_name,
398+
method_name=_method_name)
399+
application_dict[model_constants.PLAN_DIR] = new_source_name
400+
313401
def _get_plan_path(self, plan_path, archive_file, app_source_name, application_name, application_dict):
402+
_method_name = '_get_plan_path'
314403
plan_dir = None
315404
if model_constants.PLAN_DIR in application_dict:
316405
plan_dir = application_dict[model_constants.PLAN_DIR]
317406
del application_dict[model_constants.PLAN_DIR]
318407
plan_file_name = self._resolve_deployment_plan_path(plan_dir, plan_path)
319408
if self._model_context.is_remote():
320-
new_plan_name = archive_file.getApplicationPlanArchivePath(plan_file_name)
409+
if plan_file_name.endswith('plan'):
410+
new_plan_name = archive_file.getApplicationPlanDirArchivePath(plan_file_name)
411+
else:
412+
new_plan_name = archive_file.getApplicationPlanArchivePath(plan_file_name)
321413
self.add_to_remote_map(plan_path, new_plan_name,
322414
WLSDeployArchive.ArchiveEntryType.APPLICATION_PLAN.name())
323415
elif not self._model_context.skip_archive():
@@ -338,6 +430,7 @@ def _get_plan_path(self, plan_path, archive_file, app_source_name, application_n
338430
raise de
339431

340432
return new_plan_name
433+
341434
def _resolve_deployment_plan_path(self, plan_dir, plan_path):
342435
"""
343436
Find the deployment plan absolute file path.

0 commit comments

Comments
 (0)