Skip to content

Commit 2446aaf

Browse files
committed
Merge branch 'add-OHS-image' into 'main'
Added support for OHS installers and OHS recommended patching See merge request weblogic-cloud/weblogic-image-tool!460
2 parents 5049ac6 + 676b876 commit 2446aaf

File tree

10 files changed

+134
-76
lines changed

10 files changed

+134
-76
lines changed

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

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33

44
package com.oracle.weblogic.imagetool.aru;
55

6-
import java.util.ArrayList;
76
import java.util.List;
87
import java.util.Map;
8+
import java.util.Objects;
99
import java.util.stream.Collectors;
10+
import java.util.stream.Stream;
1011
import javax.xml.xpath.XPathExpressionException;
1112

1213
import com.oracle.weblogic.imagetool.logging.LoggingFacade;
@@ -156,15 +157,11 @@ public boolean isOpenAccess() {
156157
return "Open access".equals(access);
157158
}
158159

159-
public boolean notStackPatchBundle() {
160-
return !isStackPatchBundle();
161-
}
162-
163160
public boolean isStackPatchBundle() {
164161
return description != null && description.contains("STACK PATCH BUNDLE");
165162
}
166163

167-
private boolean isCoherenceFeaturePack() {
164+
public boolean isCoherenceFeaturePack() {
168165
return description != null && description.contains("Coherence 14.1.1 Feature Pack");
169166
}
170167

@@ -174,22 +171,11 @@ private boolean isCoherenceFeaturePack() {
174171
* @return a list of AruPatch
175172
* @throws XPathExpressionException if the document is not the expected format from ARU
176173
*/
177-
public static List<AruPatch> getPatches(Document patchList) throws XPathExpressionException {
178-
return getPatches(patchList, "");
179-
}
180-
181-
/**
182-
* Given an XML document with a list of patches, extract each patch into the AruPatch bean and return the list.
183-
* @param patchList an XML document with a list of patches from ARU
184-
* @param patchSelector additional XPath selector to limit the patches further
185-
* @return a list of AruPatch
186-
* @throws XPathExpressionException if the document is not the expected format from ARU
187-
*/
188-
public static List<AruPatch> getPatches(Document patchList, String patchSelector) throws XPathExpressionException {
174+
public static Stream<AruPatch> getPatches(Document patchList) throws XPathExpressionException {
189175
// create list of all patches that apply to the Linux platform
190176
NodeList nodeList = XPathUtil.nodelist(patchList,
191-
"/results/patch[./platform[@id='2000' or @id='226']]" + patchSelector);
192-
List<AruPatch> result = new ArrayList<>();
177+
"/results/patch[./platform[@id='2000' or @id='226']]");
178+
Stream.Builder<AruPatch> result = Stream.builder();
193179
for (int i = 0; i < nodeList.getLength(); i++) {
194180
if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE) {
195181
AruPatch patch = new AruPatch()
@@ -223,7 +209,7 @@ public static List<AruPatch> getPatches(Document patchList, String patchSelector
223209
}
224210
}
225211
}
226-
return result;
212+
return result.build();
227213
}
228214

229215
/**
@@ -304,19 +290,6 @@ private static AruPatch selectPatchOffline(List<AruPatch> patches, String provid
304290
return result;
305291
}
306292

307-
/**
308-
* Find and remove any Stack Patch Bundle type patches from the list.
309-
* @param patches the list to scan
310-
* @return a new list, with SPB removed
311-
*/
312-
public static List<AruPatch> removeStackPatchBundle(List<AruPatch> patches) {
313-
return patches.stream().filter(AruPatch::notStackPatchBundle).collect(Collectors.toList());
314-
}
315-
316-
public static List<AruPatch> removeCoherenceFeaturePackPatch(List<AruPatch> patches) {
317-
return patches.stream().filter(p -> !p.isCoherenceFeaturePack()).collect(Collectors.toList());
318-
}
319-
320293
@Override
321294
public String toString() {
322295
return patchId + " - " + description;
@@ -326,4 +299,22 @@ public String toString() {
326299
public int compareTo(AruPatch obj) {
327300
return version.compareTo(obj.version);
328301
}
302+
303+
@Override
304+
public boolean equals(Object o) {
305+
if (this == o) {
306+
return true;
307+
}
308+
if (o == null || getClass() != o.getClass()) {
309+
return false;
310+
}
311+
AruPatch aruPatch = (AruPatch) o;
312+
return Objects.equals(patchId, aruPatch.patchId) && Objects.equals(version, aruPatch.version)
313+
&& Objects.equals(release, aruPatch.release);
314+
}
315+
316+
@Override
317+
public int hashCode() {
318+
return Objects.hash(patchId, version, release);
319+
}
329320
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ public enum AruProduct {
2929
OWSM("12787", "Oracle Webservices Manager"),
3030
JDBC("9512", "Oracle JDBC for Fusion Middleware"),
3131
FIT("33256", "Middleware Common Libraries and Tools"),
32-
ODI("13724", "Oracle Data Integrator")
32+
ODI("13724", "Oracle Data Integrator"),
33+
OSS("16609", "Oracle Security Service"),
34+
OAM_WG("18388", "Oracle Access Manager Web Gates"),
3335
;
3436

3537
private final String productId;

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

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
package com.oracle.weblogic.imagetool.aru;
55

66
import java.io.File;
7+
import java.io.FileNotFoundException;
78
import java.io.IOException;
89
import java.io.StringWriter;
910
import java.net.UnknownHostException;
1011
import java.util.ArrayList;
12+
import java.util.Collection;
1113
import java.util.Collections;
1214
import java.util.List;
15+
import java.util.stream.Collectors;
16+
import java.util.stream.Stream;
1317
import javax.xml.xpath.XPathExpressionException;
1418

1519
import com.github.mustachejava.DefaultMustacheFactory;
@@ -30,6 +34,7 @@
3034
import static com.oracle.weblogic.imagetool.util.Constants.CONFLICTCHECKER_URL;
3135
import static com.oracle.weblogic.imagetool.util.Constants.RECOMMENDED_PATCHES_URL;
3236
import static com.oracle.weblogic.imagetool.util.Constants.REL_URL;
37+
import static com.oracle.weblogic.imagetool.util.Utils.not;
3338

3439
public class AruUtil {
3540

@@ -135,7 +140,10 @@ List<AruPatch> getLatestPsu(AruProduct product, String version, String userId, S
135140
Document aruRecommendations = retry(
136141
() -> getRecommendedPatchesMetadata(product, releaseNumber, userId, password));
137142
logger.exiting();
138-
return AruPatch.removeStackPatchBundle(AruPatch.getPatches(aruRecommendations, "[./psu_bundle]"));
143+
return AruPatch.getPatches(aruRecommendations)
144+
.filter(AruPatch::isPsu)
145+
.filter(not(AruPatch::isStackPatchBundle))
146+
.collect(Collectors.toList());
139147
} catch (NoPatchesFoundException | ReleaseNotFoundException ex) {
140148
logger.exiting();
141149
return Collections.emptyList();
@@ -158,7 +166,21 @@ public List<AruPatch> getRecommendedPatches(FmwInstallerType type, String versio
158166
List<AruPatch> result = new ArrayList<>();
159167
for (AruProduct product : type.products()) {
160168
List<AruPatch> patches = getRecommendedPatches(product, version, userId, password);
169+
// temporary, until OHS stops using same release number and product ID for two different installs
170+
if (type == FmwInstallerType.OHS) {
171+
if (product == AruProduct.OHS) {
172+
patches = patches.stream().filter(p -> p.description().contains(" DB19C "))
173+
.collect(Collectors.toList());
174+
} else if (product == AruProduct.OAM_WG) {
175+
patches = patches.stream().filter(p -> p.description().contains(" DB19c "))
176+
.collect(Collectors.toList());
177+
} else if (product == AruProduct.OSS) {
178+
patches = patches.stream().filter(p -> p.description().contains(" 19C "))
179+
.collect(Collectors.toList());
180+
}
181+
}
161182
if (!patches.isEmpty()) {
183+
patches.forEach(p -> logger.info("IMG-0068", product.description(), p.patchId(), p.description()));
162184
result.addAll(patches);
163185
}
164186
}
@@ -186,9 +208,15 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
186208
String releaseNumber = getReleaseNumber(product, version, userId, password);
187209
Document aruRecommendations = retry(
188210
() -> getRecommendedPatchesMetadata(product, releaseNumber, userId, password));
189-
List<AruPatch> patches = AruPatch.removeStackPatchBundle(AruPatch.getPatches(aruRecommendations));
190-
String psuVersion = getPsuVersion(patches);
191-
if (!Utils.isEmptyString(psuVersion)) {
211+
// TODO: Need an option for the user to request the Coherence additional feature pack.
212+
List<AruPatch> patches = AruPatch.getPatches(aruRecommendations)
213+
.filter(not(AruPatch::isStackPatchBundle)) //remove Stack Patch Bundle
214+
.filter(not(AruPatch::isCoherenceFeaturePack)) //remove COH feature pack
215+
.collect(Collectors.toList());
216+
String psuVersion = getPsuVersion(product.description(), patches);
217+
if (psuVersion != null) {
218+
//repeat the same process to get recommended patches, but use the PSU release instead of the GA release
219+
// All the same patches are in the PSU release, but also the overlay patches (if any)
192220
patches.forEach(p -> logger.fine("Discarding recommended patch {0} {1}", p.patchId(), p.description()));
193221
logger.fine("Recommended patch list contains a PSU, getting recommendations for PSU version {0}",
194222
psuVersion);
@@ -198,11 +226,11 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
198226
Document psuOverrides = retry(
199227
() -> getRecommendedPatchesMetadata(product, psuReleaseNumber, userId, password));
200228

201-
patches = AruPatch.removeStackPatchBundle(AruPatch.getPatches(psuOverrides));
229+
patches = AruPatch.getPatches(psuOverrides)
230+
.filter(not(AruPatch::isStackPatchBundle)) // remove the Stack Patch Bundle patch, if returned
231+
.filter(not(AruPatch::isCoherenceFeaturePack)) // remove the Coherence feature pack, if returned
232+
.collect(Collectors.toList());
202233
}
203-
// TODO: Need an option for the user to request the Coherence additional feature pack.
204-
patches = AruPatch.removeCoherenceFeaturePackPatch(patches);
205-
patches.forEach(p -> logger.info("IMG-0068", product.description(), p.patchId(), p.description()));
206234
logger.exiting(patches);
207235
return patches;
208236
} catch (ReleaseNotFoundException nf) {
@@ -215,13 +243,15 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
215243
}
216244
}
217245

218-
private String getPsuVersion(List<AruPatch> patches) {
219-
for (AruPatch patch: patches) {
220-
if (patch.isPsu()) {
221-
// expected pattern "Oracle WebLogic Server 12.2.1.x.xxxxxx"
222-
String[] strings = patch.psuBundle().split(" ");
223-
return strings[strings.length - 1];
224-
}
246+
private String getPsuVersion(String productName, Collection<AruPatch> patches) {
247+
String psuBundle = patches.stream()
248+
.map(AruPatch::psuBundle)
249+
.filter(not(Utils::isEmptyString))
250+
.findFirst()
251+
.orElse(null);
252+
253+
if (psuBundle != null) {
254+
return psuBundle.substring(productName.length() + 1);
225255
}
226256
return null;
227257
}
@@ -435,12 +465,12 @@ List<List<String>> getPatchConflictSets(Document conflictCheckResult) throws IOE
435465
* @throws IOException if there is an error retrieving the XML from ARU
436466
* @throws XPathExpressionException if AruPatch failed while extracting patch data from the XML
437467
*/
438-
public List<AruPatch> getPatches(String bugNumber, String userId, String password)
468+
public Stream<AruPatch> getPatches(String bugNumber, String userId, String password)
439469
throws AruException, IOException, XPathExpressionException {
440470

441471
if (userId == null || password == null) {
442472
// running in offline mode (no credentials to connect to ARU)
443-
return Collections.singletonList(new AruPatch().patchId(bugNumber));
473+
return Stream.of(new AruPatch().patchId(bugNumber));
444474
}
445475

446476
String url = String.format(BUG_SEARCH_URL, bugNumber);
@@ -467,6 +497,18 @@ public List<AruPatch> getPatches(String bugNumber, String userId, String passwor
467497

468498
public String downloadAruPatch(AruPatch aruPatch, String targetDir, String username, String password)
469499
throws IOException {
500+
try {
501+
return retry(() -> downloadPatch(aruPatch, targetDir, username, password));
502+
} catch (AruException | RetryFailedException e) {
503+
logger.severe("IMG-0120");
504+
throw logger.throwing(
505+
new FileNotFoundException(Utils.getMessage("IMG-0037", aruPatch.patchId(), aruPatch.version())));
506+
}
507+
508+
}
509+
510+
private String downloadPatch(AruPatch aruPatch, String targetDir, String username, String password)
511+
throws IOException {
470512

471513
logger.entering(aruPatch);
472514

@@ -507,12 +549,16 @@ public int getRetryInterval() {
507549
return restInterval;
508550
}
509551

510-
private interface CallToRetry {
511-
Document process() throws IOException, XPathExpressionException, AruException;
552+
/**
553+
* Similar to java.util.function.Supplier.
554+
* @param <T> return type of the supplied method.
555+
*/
556+
private interface MethodToRetry<T> {
557+
T process() throws IOException, XPathExpressionException, AruException;
512558
}
513559

514560
// create an environment variable that can override the tries count (undocumented)
515-
private static Document retry(CallToRetry call) throws AruException, RetryFailedException {
561+
private static <T> T retry(MethodToRetry<T> call) throws AruException, RetryFailedException {
516562
for (int i = 0; i < rest().getMaxRetries(); i++) {
517563
try {
518564
return call.process();

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ private static AruPatch getAruPatchOnline(String patchNumber, String providedVer
9595
String userid, String password)
9696
throws XPathExpressionException, IOException, AruException {
9797

98-
List<AruPatch> patches = AruUtil.rest().getPatches(patchNumber, userid, password);
99-
// filter ARU results based on access flag (discard protected versions)
100-
patches = patches.stream().filter(AruPatch::isOpenAccess).collect(Collectors.toList());
98+
List<AruPatch> patches = AruUtil.rest().getPatches(patchNumber, userid, password)
99+
.filter(AruPatch::isOpenAccess) // filter ARU results based on access flag (discard protected versions)
100+
.collect(Collectors.toList());
101101
logger.fine("Found {0} OPatch versions for id {1}", patches.size(), patchNumber);
102102

103103
AruPatch selectedPatch;
@@ -110,10 +110,8 @@ private static AruPatch getAruPatchOnline(String patchNumber, String providedVer
110110
throw new VersionNotFoundException(patchNumber, providedVersion, patches);
111111
}
112112
} else {
113-
// Sort the patches list from highest to lowest (newest to oldest)
114-
List<AruPatch> sortedList = patches.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
115113
// Select the newest (highest numbered) patch
116-
selectedPatch = sortedList.stream().findFirst().orElse(null);
114+
selectedPatch = patches.stream().max(Comparator.naturalOrder()).orElse(null);
117115
}
118116
return selectedPatch;
119117
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ List<AruPatch> resolveUserRequestedPatches(String psuVersion)
226226
providedVersion = patchId.substring(split + 1);
227227
patchId = patchId.substring(0, split);
228228
}
229-
List<AruPatch> patchVersions = AruUtil.rest().getPatches(patchId, userId, password);
229+
List<AruPatch> patchVersions = AruUtil.rest().getPatches(patchId, userId, password)
230+
.collect(Collectors.toList());
230231

231232
// Stack Patch Bundle (SPB) is not a traditional patch. Patches in SPB are duplicates of recommended.
232233
if (patchVersions.stream().anyMatch(AruPatch::isStackPatchBundle)) {

imagetool/src/main/java/com/oracle/weblogic/imagetool/installer/FmwInstallerType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public enum FmwInstallerType {
7979
// Oracle WebCenter Sites
8080
WCS(Utils.toSet(FMW.products, AruProduct.WCS),
8181
InstallerType.FMW, InstallerType.WCS),
82-
OHS(Collections.singleton(AruProduct.OHS),
82+
OHS(Utils.toSet(AruProduct.OHS, AruProduct.OAM_WG, AruProduct.WLS, AruProduct.JDBC, AruProduct.FMWPLAT,
83+
AruProduct.OSS, AruProduct.FIT),
8384
InstallerType.OHS),
8485
ODI(Collections.singleton(AruProduct.ODI),
8586
InstallerType.ODI)

imagetool/src/main/java/com/oracle/weblogic/imagetool/util/Utils.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.Properties;
3131
import java.util.ResourceBundle;
3232
import java.util.Set;
33+
import java.util.function.Predicate;
3334
import java.util.regex.Matcher;
3435
import java.util.regex.Pattern;
3536
import java.util.stream.Collectors;
@@ -743,4 +744,20 @@ public static <T> Set<T> toSet(Collection<? extends T> start, T... elements) {
743744
public static <T> Set<T> toSet(T... array) {
744745
return toSet(Arrays.asList(array));
745746
}
747+
748+
/**
749+
* Returns a predicate for function chaining that is the negation
750+
* of the supplied predicate.
751+
*
752+
* @param <T> the type of argument
753+
* @param target value to negate
754+
* @return negated value
755+
* @throws NullPointerException if the target is null
756+
*/
757+
@SuppressWarnings("unchecked")
758+
public static <T> Predicate<T> not(Predicate<? super T> target) {
759+
//TODO: remove this method after moving to JDK 11+
760+
Objects.requireNonNull(target);
761+
return (Predicate<T>)target.negate();
762+
}
746763
}

imagetool/src/main/resources/ImageTool.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,4 @@ IMG-0116=A patch conflict was detected. The patches listed within the brackets c
118118
IMG-0117=The value for --sourceImage must not be empty.
119119
IMG-0118=Failed to clean up intermediate container images for build ID {0}
120120
IMG-0119=All parameters and options provided after the -- will be passed to the container image build command.
121+
IMG-0120=Retries exhausted, unable to download patch from Oracle. Try again later or manually add the patch to the cache to skip this download step.

imagetool/src/test/java/com/oracle/weblogic/imagetool/aru/MockAruUtil.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55

66
import java.io.IOException;
77
import java.lang.reflect.Field;
8-
import java.util.Collections;
9-
import java.util.List;
8+
import java.util.stream.Stream;
109
import javax.xml.xpath.XPathExpressionException;
1110

1211
import com.oracle.weblogic.imagetool.ResourceUtils;
@@ -28,11 +27,11 @@ Document getAllReleases(String userId, String password) {
2827
}
2928

3029
@Override
31-
public List<AruPatch> getPatches(String bugNumber, String user, String password)
30+
public Stream<AruPatch> getPatches(String bugNumber, String user, String password)
3231
throws IOException, XPathExpressionException {
3332
if (user == null || password == null) {
3433
// running in offline mode (no credentials to connect to ARU)
35-
return Collections.singletonList(new AruPatch().patchId(bugNumber));
34+
return Stream.of(new AruPatch().patchId(bugNumber));
3635
} else {
3736
return AruPatch.getPatches(
3837
ResourceUtils.getXmlFromResource("/patches/patch-" + bugNumber + ".xml"));

0 commit comments

Comments
 (0)