Skip to content

Commit 718b78f

Browse files
authored
add handling for newly released OPatch patches with new recommended flag (#226)
* add handling for newly released OPatch patches with new recommended flag * removed unused import
1 parent 383916e commit 718b78f

File tree

8 files changed

+392
-64
lines changed

8 files changed

+392
-64
lines changed

imagetool/src/main/java/com/oracle/weblogic/imagetool/aru/AruPatch.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public class AruPatch {
3434
private String downloadHost;
3535
private String downloadPath;
3636
private String fileName;
37+
private String access;
38+
private String lifecycle;
3739

3840
public String patchId() {
3941
return patchId;
@@ -103,10 +105,6 @@ public boolean isPsu() {
103105
return !Utils.isEmptyString(psuBundle);
104106
}
105107

106-
public String downloadHost() {
107-
return downloadHost;
108-
}
109-
110108
public AruPatch downloadHost(String value) {
111109
downloadHost = value;
112110
return this;
@@ -134,6 +132,28 @@ public String fileName() {
134132
return fileName;
135133
}
136134

135+
public AruPatch access(String value) {
136+
access = value;
137+
return this;
138+
}
139+
140+
public String access() {
141+
return access;
142+
}
143+
144+
public boolean isOpenAccess() {
145+
return "Open access".equals(access);
146+
}
147+
148+
public AruPatch lifecycle(String value) {
149+
lifecycle = value;
150+
return this;
151+
}
152+
153+
public boolean isRecommended() {
154+
return "Recommended".equals(lifecycle);
155+
}
156+
137157
/**
138158
* Given an XML document with a list of patches, extract each patch into the AruPatch bean and return the list.
139159
* @param patchList an XML document with a list of patches from ARU
@@ -166,6 +186,8 @@ public static List<AruPatch> getPatches(Document patchList, String patchSelector
166186
.description(XPathUtil.string(nodeList.item(i), "./bug/abstract"))
167187
.product(XPathUtil.string(nodeList.item(i), "./product/@id"))
168188
.psuBundle(XPathUtil.string(nodeList.item(i), "./psu_bundle"))
189+
.access(XPathUtil.string(nodeList.item(i), "./access"))
190+
.lifecycle(XPathUtil.string(nodeList.item(i), "./life_cycle"))
169191
.downloadHost(XPathUtil.string(nodeList.item(i), "./files/file/download_url/@host"))
170192
.downloadPath(XPathUtil.string(nodeList.item(i), "./files/file/download_url/text()"));
171193

imagetool/src/main/java/com/oracle/weblogic/imagetool/aru/AruUtil.java

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.util.List;
1111
import javax.xml.xpath.XPathExpressionException;
1212

13-
import com.oracle.weblogic.imagetool.cachestore.MultiplePatchVersionsException;
1413
import com.oracle.weblogic.imagetool.installer.FmwInstallerType;
1514
import com.oracle.weblogic.imagetool.logging.LoggingFacade;
1615
import com.oracle.weblogic.imagetool.logging.LoggingFactory;
@@ -379,11 +378,6 @@ void verifyResponse(Document response) throws AruException, XPathExpressionExcep
379378
* @throws XPathExpressionException if AruPatch failed while extracting patch data from the XML
380379
*/
381380
public List<AruPatch> getPatches(String bugNumber, String userId, String password)
382-
throws IOException, AruException, XPathExpressionException {
383-
return getPatches(bugNumber, userId, password, "");
384-
}
385-
386-
private List<AruPatch> getPatches(String bugNumber, String userId, String password, String patchSelector)
387381
throws AruException, IOException, XPathExpressionException {
388382

389383
if (userId == null || password == null) {
@@ -399,30 +393,7 @@ private List<AruPatch> getPatches(String bugNumber, String userId, String passwo
399393
} catch (NoPatchesFoundException patchEx) {
400394
throw new NoPatchesFoundException(Utils.getMessage("IMG-0086", bugNumber), patchEx);
401395
}
402-
return AruPatch.getPatches(response, patchSelector);
403-
}
404-
405-
/**
406-
* Using a bug number, search ARU for a matching patch.
407-
* @param bugNumber the bug number to query ARU
408-
* @param userId user credentials with access to OTN
409-
* @param password password for the provided userId
410-
* @return an AruPatch
411-
* @throws IOException if there is an error retrieving the XML from ARU
412-
* @throws XPathExpressionException if AruPatch failed while extracting patch data from the XML
413-
*/
414-
public AruPatch getPatch(String bugNumber, String userId, String password, String patchSelector)
415-
throws IOException, AruException, XPathExpressionException {
416-
417-
List<AruPatch> patches = getPatches(bugNumber, userId, password, patchSelector);
418-
419-
if (patches.size() == 1) {
420-
return patches.get(0);
421-
} else {
422-
MultiplePatchVersionsException mpe = new MultiplePatchVersionsException(bugNumber, patches);
423-
logger.throwing(mpe);
424-
throw mpe;
425-
}
396+
return AruPatch.getPatches(response, "");
426397
}
427398

428399
/**

imagetool/src/main/java/com/oracle/weblogic/imagetool/cachestore/OPatchFile.java

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55

66
import java.io.FileNotFoundException;
77
import java.io.IOException;
8+
import java.util.List;
89
import java.util.Set;
10+
import java.util.stream.Collectors;
11+
import java.util.stream.Stream;
912
import javax.xml.xpath.XPathExpressionException;
1013

1114
import com.oracle.weblogic.imagetool.aru.AruException;
15+
import com.oracle.weblogic.imagetool.aru.AruPatch;
1216
import com.oracle.weblogic.imagetool.aru.AruUtil;
1317
import com.oracle.weblogic.imagetool.logging.LoggingFacade;
1418
import com.oracle.weblogic.imagetool.logging.LoggingFactory;
@@ -21,41 +25,68 @@ public class OPatchFile extends PatchFile {
2125
public static final String DEFAULT_BUG_NUM = "28186730";
2226

2327
/**
24-
* An abstract OPatch file to help resolve the local file, and determine local patch version.
25-
* Default patch number for OPatch is 28186730.
28+
* Create an abstract OPatch file to help resolve the local file or download the remote patch.
2629
*
27-
* @param patchId the ID of the patch
28-
* @param userId the username to use for retrieving the patch
30+
* @param patchId bug number and optional version
31+
* @param userid the username to use for retrieving the patch
2932
* @param password the password to use with the userId to retrieve the patch
33+
* @param cache the local cache used for patch storage
34+
* @return an abstract OPatch file
3035
*/
31-
public OPatchFile(String patchId, String userId, String password, CacheStore cache)
32-
throws IOException, AruException, XPathExpressionException {
33-
super(AruUtil.rest().getPatch(getDefaultBugNum(patchId), userId, password, "[access = 'Open access']"),
34-
userId,
35-
password);
36-
37-
// when offline, use the local cache to determine newest version available for OPatch
38-
if (userId == null && password == null) {
39-
if (patchId != null && patchId.contains(CacheStore.CACHE_KEY_SEPARATOR)) {
40-
setVersion(patchId.substring(patchId.indexOf(CacheStore.CACHE_KEY_SEPARATOR) + 1));
41-
} else {
42-
setVersion(getLatestCachedVersion(cache, getDefaultBugNum(patchId)));
36+
public static OPatchFile getInstance(String patchId, String userid, String password, CacheStore cache)
37+
throws AruException, XPathExpressionException, IOException {
38+
39+
String patchNumber = patchId;
40+
String providedVersion = null;
41+
if (patchId == null) {
42+
// if the user did not provide a patch number, assume the default OPatch bug number
43+
patchNumber = DEFAULT_BUG_NUM;
44+
} else if (patchId.contains(CacheStore.CACHE_KEY_SEPARATOR)) {
45+
// if the user provides a specific version, use that version or fail. like 28186730_13.9.4.2.4
46+
int separator = patchId.indexOf(CacheStore.CACHE_KEY_SEPARATOR);
47+
patchNumber = patchId.substring(0, separator);
48+
providedVersion = patchId.substring(separator + 1);
49+
}
50+
51+
List<AruPatch> patches = AruUtil.rest().getPatches(patchNumber, userid, password);
52+
if (!isOffline(userid, password)) {
53+
// if working online with ARU metadata, filter results based on availability and ARU recommendation
54+
Stream<AruPatch> filteredList = patches.stream().filter(AruPatch::isOpenAccess);
55+
if (providedVersion == null) {
56+
filteredList = filteredList.filter(AruPatch::isRecommended);
4357
}
58+
patches = filteredList.collect(Collectors.toList());
4459
}
45-
}
4660

47-
private static String getDefaultBugNum(String patchId) {
48-
if (patchId == null) {
49-
return DEFAULT_BUG_NUM;
50-
} else {
51-
if (patchId.contains(CacheStore.CACHE_KEY_SEPARATOR)) {
52-
return patchId.substring(0, patchId.indexOf(CacheStore.CACHE_KEY_SEPARATOR));
53-
} else {
54-
return patchId;
61+
AruPatch selectedPatch = AruPatch.selectPatch(patches, providedVersion, null, null);
62+
63+
if (selectedPatch != null) {
64+
// if offline, find the latest OPatch version available in the cache
65+
if (isOffline(userid, password) && providedVersion == null) {
66+
selectedPatch.version(getLatestCachedVersion(cache, patchNumber));
5567
}
68+
return new OPatchFile(selectedPatch, userid, password);
69+
} else {
70+
throw new MultiplePatchVersionsException(patchNumber, patches);
5671
}
5772
}
5873

74+
private static boolean isOffline(String userid, String password) {
75+
return userid == null || password == null;
76+
}
77+
78+
/**
79+
* An abstract OPatch file to help resolve the local file, and determine local patch version.
80+
* Default patch number for OPatch is 28186730.
81+
*
82+
* @param patch the OPatch ARU patch
83+
* @param userId the username to use for retrieving the patch
84+
* @param password the password to use with the userId to retrieve the patch
85+
*/
86+
private OPatchFile(AruPatch patch, String userId, String password) {
87+
super(patch, userId, password);
88+
}
89+
5990
private static String getLatestCachedVersion(CacheStore cache, String patchId) {
6091
String latestVersion = "0.0.0.0.0";
6192
Set<String> keys = cache.getCacheItems().keySet();

imagetool/src/main/java/com/oracle/weblogic/imagetool/cli/menu/CommonOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ private Path createPatchesTempDirectory() throws IOException {
355355
void installOpatchInstaller(String tmpDir, String opatchBugNumber)
356356
throws IOException, XPathExpressionException, AruException {
357357
logger.entering(opatchBugNumber);
358-
String filePath = new OPatchFile(opatchBugNumber, userId, password, cache()).resolve(cache());
358+
String filePath = OPatchFile.getInstance(opatchBugNumber, userId, password, cache()).resolve(cache());
359359
String filename = new File(filePath).getName();
360360
Files.copy(Paths.get(filePath), Paths.get(tmpDir, filename));
361361
dockerfileOptions.setOPatchPatchingEnabled();

imagetool/src/main/java/com/oracle/weblogic/imagetool/cli/menu/UpdateImage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public CommandResponse call() throws Exception {
9595
String password = getPassword();
9696

9797
if (shouldUpdateOpatch()) {
98-
OPatchFile opatchFile = new OPatchFile(opatchBugNumber, userId, password, cache());
98+
OPatchFile opatchFile = OPatchFile.getInstance(opatchBugNumber, userId, password, cache());
9999
String opatchFilePath = opatchFile.resolve(cache());
100100

101101
// if there is a newer version of OPatch than contained in the image, update OPatch

imagetool/src/test/java/com/oracle/weblogic/imagetool/cachestore/CachedFileTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,15 @@ void copyFile(@TempDir Path contextDir) throws Exception {
103103
@Test
104104
void latestOpatchVersion() throws IOException, AruException, XPathExpressionException {
105105
// OPatch file should default to the default OPatch bug number and the latest version found in cache
106-
OPatchFile patchFile = new OPatchFile(null, null, null, cacheStore);
106+
OPatchFile patchFile = OPatchFile.getInstance(null, null, null, cacheStore);
107107
assertEquals(DEFAULT_BUG_NUM + "_13.9.4.0.0", patchFile.getKey(),
108108
"failed to get latest Opatch version from the cache");
109109
}
110110

111111
@Test
112112
void specificOpatchVersion() throws IOException, AruException, XPathExpressionException {
113113
// OPatch file should default to the default OPatch bug number and the latest version found in cache
114-
OPatchFile patchFile = new OPatchFile(DEFAULT_BUG_NUM + "_13.9.2.2.2", null, null, cacheStore);
114+
OPatchFile patchFile = OPatchFile.getInstance(DEFAULT_BUG_NUM + "_13.9.2.2.2", null, null, cacheStore);
115115
assertEquals(DEFAULT_BUG_NUM + "_13.9.2.2.2", patchFile.getKey(),
116116
"failed to get specific Opatch version from the cache");
117117
}

imagetool/src/test/java/com/oracle/weblogic/imagetool/cachestore/PatchFileTest.java

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public TestAruUtil() throws IOException {
8989
responseCache.put("1110001", getResource("/patch-1110001.xml"));
9090
responseCache.put("1110002", getResource("/patch-1110002.xml"));
9191
responseCache.put("1110003", getResource("/patch-1110003.xml"));
92-
92+
responseCache.put("28186730", getResource("/patch-28186730.xml"));
9393
}
9494

9595
@Override
@@ -335,4 +335,60 @@ void throwsVersionNotFound() throws Exception {
335335
assertThrows(VersionNotFoundException.class,
336336
() -> AruPatch.selectPatch(aruPatches, "12.2.1.3.0", "12.2.1.3.181016", "12.2.1.3.1"));
337337
}
338+
339+
@Test
340+
void opatchDefaultTest() throws Exception {
341+
/*
342+
* Condition:
343+
* There are 5 versions of the OPatch patch.
344+
* The user does not specify a version.
345+
* Expected:
346+
* The recommended patch from ARU should be selected.
347+
*/
348+
349+
// 28186730 has multiple patches available, but none are specified
350+
String patchId = "28186730";
351+
OPatchFile patchFile = OPatchFile.getInstance(patchId, "x", "x", cacheStore);
352+
353+
String filePath = patchFile.resolve(cacheStore);
354+
355+
assertNotNull(filePath, "Patch resolve() failed to get file path from XML");
356+
assertEquals("13.9.4.2.4", patchFile.getVersion(), "wrong version selected");
357+
String filePathFromCache = cacheStore.getValueFromCache(patchId + "_13.9.4.2.4");
358+
assertNotNull(filePathFromCache, "Could not find new patch in cache");
359+
assertEquals(filePath, filePathFromCache, "Patch in cache does not match");
360+
}
361+
362+
@Test
363+
void opatchProvidedVersionTest() throws Exception {
364+
/*
365+
* Condition:
366+
* There are 5 versions of the OPatch patch.
367+
* The user specifies a specific version.
368+
* Expected:
369+
* The provided version of the patch is selected.
370+
*/
371+
372+
// 28186730 has multiple patches available, but none are specified
373+
String patchId = "28186730_13.9.4.2.5";
374+
OPatchFile patchFile = OPatchFile.getInstance(patchId, "x", "x", cacheStore);
375+
376+
assertEquals("13.9.4.2.5", patchFile.getVersion(), "wrong version selected");
377+
}
378+
379+
@Test
380+
void opatchProvidedWrongVersionTest() {
381+
/*
382+
* Condition:
383+
* There are 5 versions of the OPatch patch.
384+
* The user specifies a specific version.
385+
* Expected:
386+
* The provided version of the patch is selected.
387+
*/
388+
389+
// 28186730 has multiple patches available, but none are specified
390+
String patchId = "28186730_13.9.4.2.2";
391+
assertThrows(VersionNotFoundException.class, () ->
392+
OPatchFile.getInstance(patchId, "x", "x", cacheStore));
393+
}
338394
}

0 commit comments

Comments
 (0)