-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile.slim
More file actions
113 lines (102 loc) · 5.67 KB
/
Copy pathDockerfile.slim
File metadata and controls
113 lines (102 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# syntax=docker/dockerfile:1
# Slim image: populate the Maven local repository with ONLY the org.openprojectx.* artifacts this
# project uses (the bigdata-test framework + its transitive openprojectx modules, the java-dns
# agent, and the hadoop-native-loader Maven plugin), each with its -sources jar.
#
# CONFIG-DRIVEN: the artifact list is NOT hardcoded here. It is discovered by scanning every project
# POM (parent + all modules) for org.openprojectx.* <dependency>/<plugin> entries, with their
# ${...} version placeholders resolved from the parent <properties>. So adding an openprojectx
# dependency to any module pom (e.g. spark-test-bom/pom.xml) or bumping a *.version property flows
# into this image automatically -- no edits to this Dockerfile needed.
#
# It does a small breadth-first walk over the openprojectx POMs only (each fetched with
# dependency:get -Dtransitive=false), so it never resolves the huge/slow Spark/Hadoop/Cloudera
# graph -- only the openprojectx closure is downloaded.
FROM maven:3.9-eclipse-temurin-17
ARG HTTP_PROXY=""
ARG HTTPS_PROXY=""
ARG NO_PROXY=""
ENV HTTP_PROXY=${HTTP_PROXY} HTTPS_PROXY=${HTTPS_PROXY} NO_PROXY=${NO_PROXY} \
http_proxy=${HTTP_PROXY} https_proxy=${HTTPS_PROXY} no_proxy=${NO_PROXY}
WORKDIR /workspace/spark-test
# Copy the project POMs (parent + every module pom) OUTSIDE the working directory, so Maven never
# auto-discovers them as a (broken) reactor -- the modules' sources are not in this build context,
# which would make every dependency:get fail. --parents preserves each pom's path, and the ./*/pom.xml
# glob picks up any module automatically, so new modules need no change here either.
COPY --parents ./pom.xml ./*/pom.xml /tmp/poms/
RUN <<'SCRIPT'
set -eux
REPOS="central::default::https://repo1.maven.org/maven2,cloudera::default::https://repository.cloudera.com/repository/cloudera-repos/,confluent::default::https://packages.confluent.io/maven/"
POMS=/tmp/poms
PARENT="$POMS/pom.xml"
# Build a sed script that resolves ${prop} version placeholders from the parent <properties>
# (e.g. ${bigdata-test.version} -> 0.1.9). Only single-line <key>value</key> properties are taken.
awk '
/<properties>/ { p=1; next }
/<\/properties>/ { p=0 }
p && match($0, /<[A-Za-z0-9._-]+>[^<]+<\//) {
line=$0; sub(/^[ \t]*</,"",line)
key=line; sub(/>.*/,"",key)
val=line; sub(/^[^>]*>/,"",val); sub(/<.*/,"",val)
gsub(/[&|\\]/,"\\\\&",val)
print "s|\\${" key "}|" val "|g"
}
' "$PARENT" > /tmp/props.sed
# Extracts org.openprojectx.* coordinates from <dependency> and <plugin> blocks of a POM, skipping
# this project's own reactor modules (groupId org.openprojectx.bigdata.test.example), which are
# built locally rather than fetched. Versions may still contain ${...}; they are resolved downstream.
cat > /tmp/op-deps.awk <<'AWK'
function flush() {
if (depth && g ~ /^org\.openprojectx/ && g !~ /\.example$/ && a != "" && v != "")
print g ":" a ":" v (c != "" ? ":" c : "")
depth=0; g=a=v=c=""
}
/<dependency>|<plugin>/ { g=a=v=c=""; depth=1; next }
/<\/dependency>|<\/plugin>/ { flush(); next }
depth && /<groupId>/ { t=$0; gsub(/.*<groupId>|<\/groupId>.*/,"",t); g=t }
depth && /<artifactId>/ { t=$0; gsub(/.*<artifactId>|<\/artifactId>.*/,"",t); a=t }
depth && /<version>/ { t=$0; gsub(/.*<version>|<\/version>.*/,"",t); v=t }
depth && /<classifier>/ { t=$0; gsub(/.*<classifier>|<\/classifier>.*/,"",t); c=t }
AWK
# resolve = extract openprojectx coords from the given POM(s), resolve ${...} versions, and keep
# only concrete (numeric) versions -- drops managed refs that carry no version of their own.
resolve() { awk -f /tmp/op-deps.awk "$@" | sed -f /tmp/props.sed | awk -F: '$3 ~ /^[0-9]/'; }
# Seed the queue from every project POM -- this is the config-driven entry point.
resolve $(find "$POMS" -name pom.xml | sort) | sort -u > /tmp/queue.txt
: > /tmp/done.txt
: > /tmp/failed.txt
# Breadth-first over the openprojectx closure: fetch each jar (+ -sources), then enqueue the
# openprojectx dependencies found in its own POM. The Spark/Hadoop/Cloudera graph is never walked.
# Fetches are tolerant: the BOM legitimately lists gradle-only / unreleased openprojectx artifacts
# that have no resolvable jar for this version line; those are recorded in failed.txt and skipped
# rather than failing the build.
while [ -s /tmp/queue.txt ]; do
gav="$(head -1 /tmp/queue.txt)"; sed -i 1d /tmp/queue.txt
grep -qxF "$gav" /tmp/done.txt && continue
echo "$gav" >> /tmp/done.txt
# gav is g:a:v or, for a classified artifact, g:a:v:classifier (coords carry no colons).
IFS=: read -r g a v c <<EOF
$gav
EOF
# A classifier selects a specific secondary jar (e.g. extensions:...:runtime -> -runtime.jar);
# plain entries fetch the main jar. dependency:get coords are groupId:artifactId:version:packaging:classifier.
art="$g:$a:$v"; [ -n "$c" ] && art="$g:$a:$v:jar:$c"
if mvn -B dependency:get -Dtransitive=false -DremoteRepositories="$REPOS" -Dartifact="$art"; then
mvn -B dependency:get -Dtransitive=false -DremoteRepositories="$REPOS" -Dartifact="$g:$a:$v:jar:sources" || true
pom="/root/.m2/repository/$(echo "$g" | tr . /)/$a/$v/$a-$v.pom"
[ -f "$pom" ] && resolve "$pom" >> /tmp/queue.txt || true
else
echo "$gav" >> /tmp/failed.txt
fi
done
echo "=== org.openprojectx artifacts fetched ==="
find /root/.m2/repository/org/openprojectx -name '*.jar' | sort
if [ -s /tmp/failed.txt ]; then
echo "=== openprojectx artifacts with no resolvable jar (skipped) ==="
sort -u /tmp/failed.txt
fi
# Sanity check: a config or network problem that fetches nothing must fail the build loudly.
find /root/.m2/repository/org/openprojectx -name '*.jar' | grep -q . \
|| { echo "ERROR: no org.openprojectx jars were fetched"; exit 1; }
SCRIPT
CMD ["bash"]