Skip to content

Commit 36a8d39

Browse files
authored
[prism][java] Update Prism locator to match Python SDK semantics. (#32619)
* Update PrismLocator to match the python SDK semantics. * Update validate beam release with prism RC validation instructions. * rename resolveLocation to resolveSource --------- Co-authored-by: lostluck <[email protected]>
1 parent 415fdd3 commit 36a8d39

File tree

4 files changed

+147
-45
lines changed

4 files changed

+147
-45
lines changed

runners/prism/java/src/main/java/org/apache/beam/runners/prism/PrismLocator.java

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,34 +54,61 @@ class PrismLocator {
5454
private static final String PRISM_BIN_PATH = ".apache_beam/cache/prism/bin";
5555
private static final Set<PosixFilePermission> PERMS =
5656
PosixFilePermissions.fromString("rwxr-xr-x");
57-
private static final String GITHUB_DOWNLOAD_PREFIX =
58-
"https://github.com/apache/beam/releases/download";
59-
private static final String GITHUB_TAG_PREFIX = "https://github.com/apache/beam/releases/tag";
57+
private static final String GITHUB_COMMON_PREFIX = "https://github.com/apache/beam/releases/";
58+
private static final String GITHUB_DOWNLOAD_PREFIX = GITHUB_COMMON_PREFIX + "download";
59+
private static final String GITHUB_TAG_PREFIX = GITHUB_COMMON_PREFIX + "tag";
6060

6161
private final PrismPipelineOptions options;
6262

6363
PrismLocator(PrismPipelineOptions options) {
6464
this.options = options;
6565
}
6666

67+
String resolveSource() {
68+
String from =
69+
String.format(
70+
"%s/v%s/%s.zip", GITHUB_DOWNLOAD_PREFIX, RELEASE_INFO.getSdkVersion(), buildFileName());
71+
72+
if (Strings.isNullOrEmpty(options.getPrismLocation())) {
73+
return from;
74+
}
75+
from = options.getPrismLocation();
76+
77+
// Likely a local file, return it directly.
78+
if (!from.startsWith("http")) {
79+
return from;
80+
}
81+
82+
// Validate that it's from a safe location: A Beam Github Release
83+
checkArgument(
84+
options.getPrismLocation().startsWith(GITHUB_COMMON_PREFIX),
85+
"Provided --prismLocation URL is not an Apache Beam Github "
86+
+ "Release page URL or download URL: ",
87+
options.getPrismLocation());
88+
89+
from = options.getPrismLocation();
90+
91+
// If this is the tag prefix, then build the release download with the version
92+
// from the given url.
93+
if (options.getPrismLocation().startsWith(GITHUB_TAG_PREFIX)) {
94+
Path tagPath = Paths.get(options.getPrismLocation());
95+
Path locVersion = tagPath.getName(tagPath.getNameCount() - 1);
96+
// The "v" prefix is already included in the version name segment.
97+
from = String.format("%s/%s/%s.zip", GITHUB_DOWNLOAD_PREFIX, locVersion, buildFileName());
98+
}
99+
checkArgument(
100+
from.startsWith(GITHUB_DOWNLOAD_PREFIX),
101+
"Provided --prismLocation URL could not be resolved to a download URL. ",
102+
options.getPrismLocation());
103+
return from;
104+
}
105+
67106
/**
68107
* Downloads and prepares a Prism executable for use with the {@link PrismRunner}. The returned
69108
* {@link String} is the absolute path to the Prism executable.
70109
*/
71110
String resolve() throws IOException {
72-
73-
String from =
74-
String.format("%s/v%s/%s.zip", GITHUB_DOWNLOAD_PREFIX, getSDKVersion(), buildFileName());
75-
76-
if (!Strings.isNullOrEmpty(options.getPrismLocation())) {
77-
checkArgument(
78-
!options.getPrismLocation().startsWith(GITHUB_TAG_PREFIX),
79-
"Provided --prismLocation URL is not an Apache Beam Github "
80-
+ "Release page URL or download URL: ",
81-
from);
82-
83-
from = options.getPrismLocation();
84-
}
111+
String from = resolveSource();
85112

86113
String fromFileName = getNameWithoutExtension(from);
87114
Path to = Paths.get(userHome(), PRISM_BIN_PATH, fromFileName);
@@ -135,11 +162,6 @@ private String resolve(Path from, Path to) throws IOException {
135162
return to.toString();
136163
}
137164

138-
String buildFileName() {
139-
String version = getSDKVersion();
140-
return String.format("apache_beam-v%s-prism-%s-%s", version, os(), arch());
141-
}
142-
143165
private static void unzip(URL from, Path to) {
144166
try {
145167
unzip(from.openStream(), to);
@@ -181,6 +203,11 @@ private static String getNameWithoutExtension(String path) {
181203
.getNameWithoutExtension(path);
182204
}
183205

206+
private String buildFileName() {
207+
String version = getSDKVersion();
208+
return String.format("apache_beam-v%s-prism-%s-%s", version, os(), arch());
209+
}
210+
184211
private String getSDKVersion() {
185212
if (Strings.isNullOrEmpty(options.getPrismVersionOverride())) {
186213
return RELEASE_INFO.getSdkVersion();

runners/prism/java/src/main/java/org/apache/beam/runners/prism/PrismPipelineOptions.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,17 @@ public interface PrismPipelineOptions extends PortablePipelineOptions {
3232
@Description(
3333
"Path or URL to a prism binary, or zipped binary for the current "
3434
+ "platform (Operating System and Architecture). May also be an Apache "
35-
+ "Beam Github Release page URL, with a matching --prismVersionOverride "
36-
+ "set. This option overrides all others for finding a prism binary.")
35+
+ "Beam Github Release page URL, which be used to construct download URL for "
36+
+ " the current platform. ")
3737
String getPrismLocation();
3838

3939
void setPrismLocation(String prismLocation);
4040

4141
@Description(
4242
"Override the SDK's version for deriving the Github Release URLs for "
4343
+ "downloading a zipped prism binary, for the current platform. If "
44-
+ "set to a Github Release page URL, then it will use that release page as a base when constructing the download URL.")
44+
+ "the --prismLocation flag is set to a Github Release page URL, "
45+
+ "then it will use that release page as a base when constructing the download URL.")
4546
String getPrismVersionOverride();
4647

4748
void setPrismVersionOverride(String prismVersionOverride);

runners/prism/java/src/test/java/org/apache/beam/runners/prism/PrismLocatorTest.java

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.nio.file.SimpleFileVisitor;
3131
import java.nio.file.attribute.BasicFileAttributes;
3232
import org.apache.beam.sdk.options.PipelineOptionsFactory;
33+
import org.apache.beam.sdk.util.ReleaseInfo;
3334
import org.junit.Before;
3435
import org.junit.Ignore;
3536
import org.junit.Test;
@@ -40,6 +41,7 @@
4041
@RunWith(JUnit4.class)
4142
public class PrismLocatorTest {
4243

44+
private static final ReleaseInfo RELEASE_INFO = ReleaseInfo.getReleaseInfo();
4345
private static final Path DESTINATION_DIRECTORY = prismBinDirectory();
4446

4547
@Before
@@ -61,61 +63,102 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
6163
}
6264

6365
@Test
64-
public void givenVersionOverride_thenResolves() throws IOException {
65-
assertThat(Files.exists(DESTINATION_DIRECTORY)).isFalse();
66+
public void givenVersionOverride_thenResolvesLocation() throws IOException {
67+
PrismPipelineOptions options = options();
68+
options.setPrismVersionOverride("2.57.0-RC1");
69+
70+
PrismLocator underTest = new PrismLocator(options);
71+
String got = underTest.resolveSource();
72+
73+
assertThat(got)
74+
.contains(
75+
"https://github.com/apache/beam/releases/download/v" + RELEASE_INFO.getSdkVersion());
76+
assertThat(got).contains("apache_beam-v2.57.0-RC1-prism");
77+
assertThat(got).contains(".zip");
78+
}
79+
80+
// This testcase validates a user override to download a different release version specifically.
81+
@Test
82+
public void givenHttpPrismLocationOption_thenResolvesLocation() throws IOException {
83+
PrismPipelineOptions options = options();
84+
String want =
85+
"https://github.com/apache/beam/releases/download/v2.57.0/apache_beam-v2.57.0-prism-darwin-arm64.zip";
86+
options.setPrismLocation(want);
87+
88+
PrismLocator underTest = new PrismLocator(options);
89+
String got = underTest.resolveSource();
90+
91+
assertThat(got).isEqualTo(want);
92+
}
93+
94+
// This testcase is the Release Validation behavior, where we provide an RC option, but
95+
// need to resolve the download for the non-RC version.
96+
// Copy the URL directly, and set the location, override the file's RC version with the final
97+
// version.
98+
@Test
99+
public void givenRCGithubTagPrismLocationOption_thenResolvesLocation() {
66100
PrismPipelineOptions options = options();
101+
options.setPrismLocation("https://github.com/apache/beam/releases/tag/v2.57.0-RC1/");
67102
options.setPrismVersionOverride("2.57.0");
103+
68104
PrismLocator underTest = new PrismLocator(options);
69-
String got = underTest.resolve();
70-
assertThat(got).contains(DESTINATION_DIRECTORY.toString());
71-
assertThat(got).contains("2.57.0");
72-
Path gotPath = Paths.get(got);
73-
assertThat(Files.exists(gotPath)).isTrue();
105+
String got = underTest.resolveSource();
106+
107+
assertThat(got)
108+
.contains(
109+
"https://github.com/apache/beam/releases/download/v2.57.0-RC1/apache_beam-v2.57.0-prism");
110+
assertThat(got).contains(".zip");
74111
}
75112

76113
@Test
77-
public void givenHttpPrismLocationOption_thenResolves() throws IOException {
78-
assertThat(Files.exists(DESTINATION_DIRECTORY)).isFalse();
114+
public void givenRCGithubTagPrismLocationOptionNoTrailingSlash_thenResolvesLocation() {
79115
PrismPipelineOptions options = options();
80-
options.setPrismLocation(
81-
"https://github.com/apache/beam/releases/download/v2.57.0/apache_beam-v2.57.0-prism-darwin-arm64.zip");
116+
options.setPrismLocation("https://github.com/apache/beam/releases/tag/v2.57.0-RC2");
117+
options.setPrismVersionOverride("2.57.0");
118+
82119
PrismLocator underTest = new PrismLocator(options);
83-
String got = underTest.resolve();
84-
assertThat(got).contains(DESTINATION_DIRECTORY.toString());
85-
Path gotPath = Paths.get(got);
86-
assertThat(Files.exists(gotPath)).isTrue();
120+
String got = underTest.resolveSource();
121+
122+
assertThat(got)
123+
.contains(
124+
"https://github.com/apache/beam/releases/download/v2.57.0-RC2/apache_beam-v2.57.0-prism");
125+
assertThat(got).contains(".zip");
87126
}
88127

89128
@Test
90129
public void givenFilePrismLocationOption_thenResolves() throws IOException {
91130
assertThat(Files.exists(DESTINATION_DIRECTORY)).isFalse();
92131
PrismPipelineOptions options = options();
93132
options.setPrismLocation(getLocalPrismBuildOrIgnoreTest());
133+
94134
PrismLocator underTest = new PrismLocator(options);
95135
String got = underTest.resolve();
136+
96137
assertThat(got).contains(DESTINATION_DIRECTORY.toString());
97138
Path gotPath = Paths.get(got);
98139
assertThat(Files.exists(gotPath)).isTrue();
99140
}
100141

101142
@Test
102-
public void givenGithubTagPrismLocationOption_thenThrows() {
143+
public void givenIncorrectGithubPrismLocationOption_thenThrows() {
103144
PrismPipelineOptions options = options();
145+
// This is an incorrect github download path. Downloads are under /download/ not tag.
104146
options.setPrismLocation(
105147
"https://github.com/apache/beam/releases/tag/v2.57.0/apache_beam-v2.57.0-prism-darwin-amd64.zip");
148+
106149
PrismLocator underTest = new PrismLocator(options);
107-
IllegalArgumentException error =
108-
assertThrows(IllegalArgumentException.class, underTest::resolve);
109-
assertThat(error.getMessage())
110-
.contains(
111-
"Provided --prismLocation URL is not an Apache Beam Github Release page URL or download URL");
150+
151+
RuntimeException error = assertThrows(RuntimeException.class, underTest::resolve);
152+
// Message should contain the incorrectly constructed download link.
153+
assertThat(error.getMessage()).contains(".zip/apache_beam");
112154
}
113155

114156
@Test
115157
@Ignore // TODO: use mock site. Currently failing with response code 500 instead of 404
116158
public void givenPrismLocation404_thenThrows() {
117159
PrismPipelineOptions options = options();
118160
options.setPrismLocation("https://example.com/i/dont/exist.zip");
161+
119162
PrismLocator underTest = new PrismLocator(options);
120163
RuntimeException error = assertThrows(RuntimeException.class, underTest::resolve);
121164
assertThat(error.getMessage()).contains("NotFoundException");

website/www/site/content/en/blog/validate-beam-release.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,37 @@ With that, the Beam version in your environment will be the latest release
107107
candidate, and you can go ahead and run your tests to verify that everything
108108
works well.
109109

110+
### Validating Prism Runner RC against RC SDKs
111+
112+
Replace v2.59.0-RC1 with the tag of the RC version being validated.
113+
114+
#### Python
115+
116+
To validate the prism runner with Python,
117+
`--runner=PrismRunner --prism_location=https://github.com/apache/beam/releases/tag/v2.59.0-RC1 --prism_beam_version_override=v2.59.0`
118+
119+
* The `runner` flag sets Beam to use Prism.
120+
* The `prism_location` sets the source of Prism assets.
121+
* The `prism_beam_version_override` flag sets what those artifacts are labeled as.
122+
* The assets are packaged as the final release version, so the override is required.
123+
124+
#### Java
125+
126+
For Gradle, add the Prism, and the JAMM depdendencies to your `build.gradle`.
127+
128+
```
129+
implementation "org.apache.beam:beam-runners-prism-java:2.59.0"
130+
implementation "com.github.jbellis:jamm:0.4.0"
131+
```
132+
133+
Then add the following flags, substituting the version accordingly.
134+
135+
`--runner=PrismRunner --prismLocation="https://github.com/apache/beam/releases/tag/v2.59.0-RC1/" --prismVersionOverride=v2.59.0
136+
137+
* The `runner` flag sets Beam to use Prism.
138+
* The `prismLocation` sets the source of Prism assets, specifically the zip file of the version in question.
139+
140+
110141
### Configuring a Go build to validate a Beam release candidate
111142

112143
For Go SDK releases, you can fetch the Go SDK RC using [`go get`](https://golang.org/ref/mod#go-get),

0 commit comments

Comments
 (0)