Skip to content
This repository was archived by the owner on Nov 22, 2020. It is now read-only.

Commit c49bb97

Browse files
authored
factor out path building logic (#90)
* factor out path building logic * add test coverage; rename to... url Signed-off-by: Julien Le Dem <[email protected]>
1 parent c51726b commit c49bb97

File tree

6 files changed

+366
-219
lines changed

6 files changed

+366
-219
lines changed

src/main/java/marquez/client/MarquezClient.java

Lines changed: 32 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,22 @@
1414

1515
package marquez.client;
1616

17-
import static com.google.common.base.Preconditions.checkArgument;
18-
import static java.time.format.DateTimeFormatter.ISO_INSTANT;
17+
import static marquez.client.models.RunState.ABORTED;
18+
import static marquez.client.models.RunState.COMPLETED;
19+
import static marquez.client.models.RunState.FAILED;
20+
import static marquez.client.models.RunState.RUNNING;
1921

2022
import com.fasterxml.jackson.annotation.JsonCreator;
2123
import com.fasterxml.jackson.annotation.JsonProperty;
2224
import com.fasterxml.jackson.core.type.TypeReference;
2325
import com.google.common.annotations.VisibleForTesting;
2426
import com.google.common.collect.ImmutableList;
25-
import com.google.common.collect.ImmutableMap;
2627
import com.google.common.collect.ImmutableSet;
2728
import java.io.IOException;
2829
import java.io.InputStream;
2930
import java.net.URL;
3031
import java.time.Instant;
3132
import java.util.List;
32-
import java.util.Map;
3333
import java.util.Properties;
3434
import java.util.Set;
3535
import javax.annotation.Nullable;
@@ -52,9 +52,8 @@
5252

5353
@Slf4j
5454
public class MarquezClient {
55-
@VisibleForTesting static final String BASE_PATH = "/api/v1";
5655

57-
static final URL DEFAULT_BASE_URL = Utils.toUrl("http://localhost:8080" + BASE_PATH);
56+
static final URL DEFAULT_BASE_URL = Utils.toUrl("http://localhost:8080");
5857

5958
@VisibleForTesting static final int DEFAULT_LIMIT = 100;
6059
@VisibleForTesting static final int DEFAULT_OFFSET = 0;
@@ -81,13 +80,12 @@ public MarquezClient(final URL baseUrl) {
8180

8281
public Namespace createNamespace(
8382
@NonNull String namespaceName, @NonNull NamespaceMeta namespaceMeta) {
84-
final String bodyAsJson =
85-
http.put(url.from("/namespaces/%s", namespaceName), namespaceMeta.toJson());
83+
final String bodyAsJson = http.put(url.toNamespaceUrl(namespaceName), namespaceMeta.toJson());
8684
return Namespace.fromJson(bodyAsJson);
8785
}
8886

8987
public Namespace getNamespace(@NonNull String namespaceName) {
90-
final String bodyAsJson = http.get(url.from("/namespaces/%s", namespaceName));
88+
final String bodyAsJson = http.get(url.toNamespaceUrl(namespaceName));
9189
return Namespace.fromJson(bodyAsJson);
9290
}
9391

@@ -96,26 +94,26 @@ public List<Namespace> listNamespaces() {
9694
}
9795

9896
public List<Namespace> listNamespaces(int limit, int offset) {
99-
final String bodyAsJson = http.get(url.from("/namespaces", newQueryParamsWith(limit, offset)));
97+
final String bodyAsJson = http.get(url.toListNamespacesUrl(limit, offset));
10098
return Namespaces.fromJson(bodyAsJson).getValue();
10199
}
102100

103101
public Source createSource(@NonNull String sourceName, @NonNull SourceMeta sourceMeta) {
104-
final String bodyAsJson = http.put(url.from("/sources/%s", sourceName), sourceMeta.toJson());
102+
final String bodyAsJson = http.put(url.toSourceUrl(sourceName), sourceMeta.toJson());
105103
return Source.fromJson(bodyAsJson);
106104
}
107105

108106
public Source getSource(@NonNull String sourceName) {
109-
final String bodyAsJson = http.get(url.from("/sources/%s", sourceName));
107+
final String bodyAsJson = http.get(url.toSourceUrl(sourceName));
110108
return Source.fromJson(bodyAsJson);
111109
}
112110

113-
public List<Source> listSources(String namespaceName) {
114-
return listSources(namespaceName, DEFAULT_LIMIT, DEFAULT_OFFSET);
111+
public List<Source> listSources() {
112+
return listSources(DEFAULT_LIMIT, DEFAULT_OFFSET);
115113
}
116114

117-
public List<Source> listSources(@NonNull String namespaceName, int limit, int offset) {
118-
final String bodyAsJson = http.get(url.from("/sources", newQueryParamsWith(limit, offset)));
115+
public List<Source> listSources(int limit, int offset) {
116+
final String bodyAsJson = http.get(url.toListSourcesUrl(limit, offset));
119117
return Sources.fromJson(bodyAsJson).getValue();
120118
}
121119

@@ -124,15 +122,12 @@ public Dataset createDataset(
124122
@NonNull String datasetName,
125123
@NonNull DatasetMeta datasetMeta) {
126124
final String bodyAsJson =
127-
http.put(
128-
url.from("/namespaces/%s/datasets/%s", namespaceName, datasetName),
129-
datasetMeta.toJson());
125+
http.put(url.toDatasetUrl(namespaceName, datasetName), datasetMeta.toJson());
130126
return Dataset.fromJson(bodyAsJson);
131127
}
132128

133129
public Dataset getDataset(@NonNull String namespaceName, @NonNull String datasetName) {
134-
final String bodyAsJson =
135-
http.get(url.from("/namespaces/%s/datasets/%s", namespaceName, datasetName));
130+
final String bodyAsJson = http.get(url.toDatasetUrl(namespaceName, datasetName));
136131
return Dataset.fromJson(bodyAsJson);
137132
}
138133

@@ -141,17 +136,13 @@ public List<Dataset> listDatasets(String namespaceName) {
141136
}
142137

143138
public List<Dataset> listDatasets(@NonNull String namespaceName, int limit, int offset) {
144-
final String bodyAsJson =
145-
http.get(
146-
url.from("/namespaces/%s/datasets", newQueryParamsWith(limit, offset), namespaceName));
139+
final String bodyAsJson = http.get(url.toListDatasetsUrl(namespaceName, limit, offset));
147140
return Datasets.fromJson(bodyAsJson).getValue();
148141
}
149142

150143
public Dataset tagDatasetWith(
151144
@NonNull String namespaceName, @NonNull String datasetName, @NonNull String tagName) {
152-
final String bodyAsJson =
153-
http.post(
154-
url.from("/namespaces/%s/datasets/%s/tags/%s", namespaceName, datasetName, tagName));
145+
final String bodyAsJson = http.post(url.toDatasetTagUrl(namespaceName, datasetName, tagName));
155146
return Dataset.fromJson(bodyAsJson);
156147
}
157148

@@ -161,22 +152,18 @@ public Dataset tagFieldWith(
161152
@NonNull String fieldName,
162153
@NonNull String tagName) {
163154
final String bodyAsJson =
164-
http.post(
165-
url.from(
166-
"/namespaces/%s/datasets/%s/fields/%s/tags/%s",
167-
namespaceName, datasetName, fieldName, tagName));
155+
http.post(url.toFieldTagURL(namespaceName, datasetName, fieldName, tagName));
168156
return Dataset.fromJson(bodyAsJson);
169157
}
170158

171159
public Job createJob(
172160
@NonNull String namespaceName, @NonNull String jobName, @NonNull JobMeta jobMeta) {
173-
final String bodyAsJson =
174-
http.put(url.from("/namespaces/%s/jobs/%s", namespaceName, jobName), jobMeta.toJson());
161+
final String bodyAsJson = http.put(url.toJobUrl(namespaceName, jobName), jobMeta.toJson());
175162
return Job.fromJson(bodyAsJson);
176163
}
177164

178165
public Job getJob(@NonNull String namespaceName, @NonNull String jobName) {
179-
final String bodyAsJson = http.get(url.from("/namespaces/%s/jobs/%s", namespaceName, jobName));
166+
final String bodyAsJson = http.get(url.toJobUrl(namespaceName, jobName));
180167
return Job.fromJson(bodyAsJson);
181168
}
182169

@@ -185,8 +172,7 @@ public List<Job> listJobs(String namespaceName) {
185172
}
186173

187174
public List<Job> listJobs(@NonNull String namespaceName, int limit, int offset) {
188-
final String bodyAsJson =
189-
http.get(url.from("/namespaces/%s/jobs", newQueryParamsWith(limit, offset), namespaceName));
175+
final String bodyAsJson = http.get(url.toListJobsUrl(namespaceName, limit, offset));
190176
return Jobs.fromJson(bodyAsJson).getValue();
191177
}
192178

@@ -200,8 +186,7 @@ private Run createRun(
200186
@NonNull RunMeta runMeta,
201187
boolean markRunAsRunning) {
202188
final String bodyAsJson =
203-
http.post(
204-
url.from("/namespaces/%s/jobs/%s/runs", namespaceName, jobName), runMeta.toJson());
189+
http.post(url.toCreateRunUrl(namespaceName, jobName), runMeta.toJson());
205190
final Run run = Run.fromJson(bodyAsJson);
206191
return (markRunAsRunning) ? markRunAsRunning(run.getId()) : run;
207192
}
@@ -211,7 +196,7 @@ public Run createRunAndStart(String namespaceName, String jobName, RunMeta runMe
211196
}
212197

213198
public Run getRun(@NonNull String runId) {
214-
final String bodyAsJson = http.get(url.from("/jobs/runs/%s", runId));
199+
final String bodyAsJson = http.get(url.toRunUrl(runId));
215200
return Run.fromJson(bodyAsJson);
216201
}
217202

@@ -221,11 +206,7 @@ public List<Run> listRuns(String namespaceName, String jobName) {
221206

222207
public List<Run> listRuns(
223208
@NonNull String namespaceName, @NonNull String jobName, int limit, int offset) {
224-
final String bodyAsJson =
225-
http.get(
226-
url.from(
227-
"/namespaces/%s/jobs/%s/runs",
228-
newQueryParamsWith(limit, offset), namespaceName, jobName));
209+
final String bodyAsJson = http.get(url.toListRunsUrl(namespaceName, jobName, limit, offset));
229210
return Runs.fromJson(bodyAsJson).getValue();
230211
}
231212

@@ -234,77 +215,51 @@ public Run markRunAs(String runId, RunState runState) {
234215
}
235216

236217
public Run markRunAs(String runId, @NonNull RunState runState, @Nullable Instant at) {
237-
switch (runState) {
238-
case RUNNING:
239-
return markRunAsRunning(runId, at);
240-
case COMPLETED:
241-
return markRunAsCompleted(runId, at);
242-
case ABORTED:
243-
return markRunAsAborted(runId, at);
244-
case FAILED:
245-
return markRunAsFailed(runId, at);
246-
default:
247-
throw new IllegalArgumentException(
248-
String.format("Unexpected run state: %s", runState.name()));
249-
}
218+
final String bodyAsJson = http.post(url.toRunTransitionUrl(runId, runState, at));
219+
return Run.fromJson(bodyAsJson);
250220
}
251221

252222
public Run markRunAsRunning(String runId) {
253223
return markRunAsRunning(runId, null);
254224
}
255225

256226
public Run markRunAsRunning(String runId, @Nullable Instant at) {
257-
return markRunWith("/jobs/runs/%s/start", runId, at);
227+
return markRunAs(runId, RUNNING, at);
258228
}
259229

260230
public Run markRunAsCompleted(String runId) {
261231
return markRunAsCompleted(runId, null);
262232
}
263233

264234
public Run markRunAsCompleted(String runId, @Nullable Instant at) {
265-
return markRunWith("/jobs/runs/%s/complete", runId, at);
235+
return markRunAs(runId, COMPLETED, at);
266236
}
267237

268238
public Run markRunAsAborted(String runId) {
269239
return markRunAsAborted(runId, null);
270240
}
271241

272242
public Run markRunAsAborted(String runId, @Nullable Instant at) {
273-
return markRunWith("/jobs/runs/%s/abort", runId, at);
243+
return markRunAs(runId, ABORTED, at);
274244
}
275245

276246
public Run markRunAsFailed(String runId) {
277247
return markRunAsFailed(runId, null);
278248
}
279249

280250
public Run markRunAsFailed(String runId, @Nullable Instant at) {
281-
return markRunWith("/jobs/runs/%s/fail", runId, at);
282-
}
283-
284-
private Run markRunWith(String pathTemplate, @NonNull String runId, @Nullable Instant at) {
285-
final String bodyAsJson = http.post(url.from(pathTemplate, newQueryParamsWith(at), runId));
286-
return Run.fromJson(bodyAsJson);
251+
return markRunAs(runId, FAILED, at);
287252
}
288253

289254
public Set<Tag> listTags() {
290255
return listTags(DEFAULT_LIMIT, DEFAULT_OFFSET);
291256
}
292257

293258
public Set<Tag> listTags(int limit, int offset) {
294-
final String bodyAsJson = http.get(url.from("/tags", newQueryParamsWith(limit, offset)));
259+
final String bodyAsJson = http.get(url.toListTagsUrl(limit, offset));
295260
return Tags.fromJson(bodyAsJson).getValue();
296261
}
297262

298-
private Map<String, Object> newQueryParamsWith(@Nullable Instant at) {
299-
return (at == null) ? ImmutableMap.of() : ImmutableMap.of("at", ISO_INSTANT.format(at));
300-
}
301-
302-
private Map<String, Object> newQueryParamsWith(int limit, int offset) {
303-
checkArgument(limit >= 0, "limit must be >= 0");
304-
checkArgument(offset >= 0, "offset must be >= 0");
305-
return ImmutableMap.of("limit", limit, "offset", offset);
306-
}
307-
308263
public static final class Builder {
309264
@VisibleForTesting URL baseUrl;
310265

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package marquez.client;
2+
3+
import com.google.common.annotations.VisibleForTesting;
4+
import javax.annotation.Nullable;
5+
import lombok.NonNull;
6+
import marquez.client.models.RunState;
7+
8+
class MarquezPathV1 {
9+
10+
@VisibleForTesting static final String BASE_PATH = "/api/v1";
11+
12+
@VisibleForTesting
13+
static String path(String pathTemplate, @Nullable String... pathArgs) {
14+
return BASE_PATH + String.format(pathTemplate, (Object[]) pathArgs);
15+
}
16+
17+
static String listNamespacesPath() {
18+
return path("/namespaces");
19+
}
20+
21+
static String namespacePath(String namespaceName) {
22+
return path("/namespaces/%s", namespaceName);
23+
}
24+
25+
static String sourcePath(String sourceName) {
26+
return path("/sources/%s", sourceName);
27+
}
28+
29+
static String listSourcesPath() {
30+
return path("/sources");
31+
}
32+
33+
static String listDatasetsPath(@NonNull String namespaceName) {
34+
return path("/namespaces/%s/datasets", namespaceName);
35+
}
36+
37+
static String datasetPath(String namespaceName, String datasetName) {
38+
return path("/namespaces/%s/datasets/%s", namespaceName, datasetName);
39+
}
40+
41+
static String listJobsPath(@NonNull String namespaceName) {
42+
return path("/namespaces/%s/jobs", namespaceName);
43+
}
44+
45+
static String jobPath(String namespaceName, String jobName) {
46+
return path("/namespaces/%s/jobs/%s", namespaceName, jobName);
47+
}
48+
49+
static String createRunPath(String namespaceName, String jobName) {
50+
return path("/namespaces/%s/jobs/%s/runs", namespaceName, jobName);
51+
}
52+
53+
static String runPath(@NonNull String runId) {
54+
return path("/jobs/runs/%s", runId);
55+
}
56+
57+
static String listRunsPath(@NonNull String namespaceName, @NonNull String jobName) {
58+
return path("/namespaces/%s/jobs/%s/runs", namespaceName, jobName);
59+
}
60+
61+
static String runTransitionPath(String runId, RunState runState) {
62+
final String transition;
63+
switch (runState) {
64+
case RUNNING:
65+
transition = "start";
66+
break;
67+
case COMPLETED:
68+
transition = "complete";
69+
break;
70+
case ABORTED:
71+
transition = "abort";
72+
break;
73+
case FAILED:
74+
transition = "fail";
75+
break;
76+
default:
77+
throw new IllegalArgumentException(
78+
String.format("Unexpected run state: %s", runState.name()));
79+
}
80+
return path("/jobs/runs/%s/%s", runId, transition);
81+
}
82+
83+
static String datasetTagPath(
84+
@NonNull String namespaceName, @NonNull String datasetName, @NonNull String tagName) {
85+
return path("/namespaces/%s/datasets/%s/tags/%s", namespaceName, datasetName, tagName);
86+
}
87+
88+
static String fieldTagPath(
89+
String namespaceName, String datasetName, String fieldName, String tagName) {
90+
return path(
91+
"/namespaces/%s/datasets/%s/fields/%s/tags/%s",
92+
namespaceName, datasetName, fieldName, tagName);
93+
}
94+
95+
static String listTagsPath() {
96+
return path("/tags");
97+
}
98+
}

0 commit comments

Comments
 (0)