Skip to content

Commit 4194d28

Browse files
davidsharp7sharpd
andauthored
add DELETE end point for dataset tags (#2698)
* add DELETE end point for dataset tags Signed-off-by: sharpd <[email protected]> * ran code linter to re-format Signed-off-by: sharpd <[email protected]> * add integration tests and Marquez client Signed-off-by: sharpd <[email protected]> --------- Signed-off-by: sharpd <[email protected]> Co-authored-by: sharpd <[email protected]>
1 parent 033cea3 commit 4194d28

File tree

6 files changed

+180
-2
lines changed

6 files changed

+180
-2
lines changed

api/src/main/java/marquez/api/DatasetResource.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,33 @@ public Response tag(
198198
return Response.ok(dataset).build();
199199
}
200200

201+
@Timed
202+
@ResponseMetered
203+
@ExceptionMetered
204+
@DELETE
205+
@Path("/{dataset}/tags/{tag}")
206+
@Produces(APPLICATION_JSON)
207+
public Response deleteDatasetTag(
208+
@PathParam("namespace") NamespaceName namespaceName,
209+
@PathParam("dataset") DatasetName datasetName,
210+
@PathParam("tag") TagName tagName) {
211+
throwIfNotExists(namespaceName);
212+
throwIfNotExists(namespaceName, datasetName);
213+
214+
log.info(
215+
"Deleted tag '{}' from dataset '{}' on namespace '{}'",
216+
tagName.getValue(),
217+
datasetName.getValue(),
218+
namespaceName.getValue());
219+
datasetService.deleteDatasetTag(
220+
namespaceName.getValue(), datasetName.getValue(), tagName.getValue());
221+
Dataset dataset =
222+
datasetService
223+
.findDatasetByName(namespaceName.getValue(), datasetName.getValue())
224+
.orElseThrow(() -> new DatasetNotFoundException(datasetName));
225+
return Response.ok(dataset).build();
226+
}
227+
201228
@Timed
202229
@ResponseMetered
203230
@ExceptionMetered

api/src/main/java/marquez/db/DatasetDao.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,33 @@ DatasetRow upsert(
272272
""")
273273
Optional<DatasetRow> delete(String namespaceName, String name);
274274

275+
@SqlUpdate(
276+
"""
277+
DELETE FROM datasets_tag_mapping dtm
278+
WHERE EXISTS (
279+
SELECT 1
280+
FROM
281+
datasets d
282+
JOIN
283+
tags t
284+
ON
285+
d.uuid = dtm.dataset_uuid
286+
AND
287+
t.uuid = dtm.tag_uuid
288+
JOIN
289+
namespaces n
290+
ON
291+
d.namespace_uuid = n.uuid
292+
WHERE
293+
d.name = :datasetName
294+
AND
295+
t.name = :tagName
296+
AND
297+
n.name = :namespaceName
298+
);
299+
""")
300+
void deleteDatasetTag(String namespaceName, String datasetName, String tagName);
301+
275302
@Transaction
276303
default Dataset upsertDatasetMeta(
277304
NamespaceName namespaceName, DatasetName datasetName, DatasetMeta datasetMeta) {

api/src/test/java/marquez/api/BaseResourceIntegrationTest.java

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,16 @@
55

66
package marquez.api;
77

8+
import static marquez.common.models.CommonModelGenerator.newConnectionUrlFor;
9+
import static marquez.common.models.CommonModelGenerator.newDatasetName;
10+
import static marquez.common.models.CommonModelGenerator.newDbSourceType;
11+
import static marquez.common.models.CommonModelGenerator.newDescription;
812
import static marquez.common.models.CommonModelGenerator.newNamespaceName;
13+
import static marquez.common.models.CommonModelGenerator.newOwnerName;
14+
import static marquez.common.models.CommonModelGenerator.newSourceName;
915
import static marquez.db.DbTest.POSTGRES_14;
1016

17+
import com.google.common.collect.ImmutableSet;
1118
import io.dropwizard.testing.ConfigOverride;
1219
import io.dropwizard.testing.ResourceHelpers;
1320
import io.dropwizard.testing.junit5.DropwizardAppExtension;
@@ -16,11 +23,17 @@
1623
import io.openlineage.client.transports.HttpTransport;
1724
import java.net.URI;
1825
import java.net.URL;
26+
import java.util.Set;
1927
import marquez.MarquezApp;
2028
import marquez.MarquezConfig;
2129
import marquez.client.MarquezClient;
2230
import marquez.client.Utils;
31+
import marquez.client.models.DatasetId;
32+
import marquez.client.models.DbTableMeta;
33+
import marquez.client.models.NamespaceMeta;
34+
import marquez.client.models.SourceMeta;
2335
import marquez.client.models.Tag;
36+
import marquez.common.models.SourceType;
2437
import org.junit.jupiter.api.AfterAll;
2538
import org.junit.jupiter.api.BeforeAll;
2639
import org.testcontainers.containers.PostgreSQLContainer;
@@ -56,17 +69,61 @@ abstract class BaseResourceIntegrationTest {
5669
static final Tag PII = new Tag("PII", "Personally identifiable information");
5770
static final Tag SENSITIVE = new Tag("SENSITIVE", "Contains sensitive information");
5871

72+
// Namespace
5973
static String NAMESPACE_NAME;
60-
static DropwizardAppExtension<MarquezConfig> MARQUEZ_APP;
74+
static String NAMESPACE_DESCRIPTION;
75+
static String OWNER_NAME;
76+
77+
// Source
78+
static String SOURCE_TYPE;
79+
static String SOURCE_NAME;
80+
static URI CONNECTION_URL;
81+
static String SOURCE_DESCRIPTION;
82+
83+
// Dataset
84+
static String DB_TABLE_SOURCE_TYPE;
85+
static String DB_TABLE_SOURCE_NAME;
86+
static URI DB_TABLE_CONNECTION_URL;
87+
static String DB_TABLE_SOURCE_DESCRIPTION;
88+
static DatasetId DB_TABLE_ID;
89+
static String DB_TABLE_NAME;
90+
static String DB_TABLE_PHYSICAL_NAME;
91+
static String DB_TABLE_DESCRIPTION;
92+
static Set<String> DB_TABLE_TAGS;
93+
static DbTableMeta DB_TABLE_META;
6194

95+
static DropwizardAppExtension<MarquezConfig> MARQUEZ_APP;
6296
static OpenLineage OL;
6397
static OpenLineageClient OL_CLIENT;
6498
static MarquezClient MARQUEZ_CLIENT;
6599

66100
@BeforeAll
67101
public static void setUpOnce() throws Exception {
68-
// (1) Use a randomly generated namespace.
102+
// (1) Use a randomly generated namespace/dataset
69103
NAMESPACE_NAME = newNamespaceName().getValue();
104+
NAMESPACE_DESCRIPTION = newDescription();
105+
OWNER_NAME = newOwnerName().getValue();
106+
107+
SOURCE_TYPE = newDbSourceType().getValue();
108+
SOURCE_NAME = newSourceName().getValue();
109+
SOURCE_DESCRIPTION = newDescription();
110+
111+
DB_TABLE_SOURCE_TYPE = SourceType.of("POSTGRESQL").getValue();
112+
DB_TABLE_SOURCE_NAME = SOURCE_NAME;
113+
DB_TABLE_SOURCE_DESCRIPTION = newDescription();
114+
DB_TABLE_ID = newDatasetIdWith(NAMESPACE_NAME);
115+
DB_TABLE_NAME = DB_TABLE_ID.getName();
116+
DB_TABLE_PHYSICAL_NAME = DB_TABLE_NAME;
117+
DB_TABLE_DESCRIPTION = newDescription();
118+
DB_TABLE_TAGS = ImmutableSet.of(PII.getName());
119+
DB_TABLE_CONNECTION_URL = newConnectionUrlFor(SourceType.of("POSTGRESQL"));
120+
DB_TABLE_META =
121+
DbTableMeta.builder()
122+
.physicalName(DB_TABLE_PHYSICAL_NAME)
123+
.sourceName(DB_TABLE_SOURCE_NAME)
124+
.tags(DB_TABLE_TAGS)
125+
.description(DB_TABLE_DESCRIPTION)
126+
.build();
70127

71128
// (2) Configure Marquez application using test configuration and database.
72129
MARQUEZ_APP =
@@ -89,6 +146,28 @@ public static void setUpOnce() throws Exception {
89146
MARQUEZ_CLIENT = MarquezClient.builder().baseUrl(url).build();
90147
}
91148

149+
protected void createNamespace(String namespaceName) {
150+
// (1) Create namespace for db table
151+
final NamespaceMeta namespaceMeta =
152+
NamespaceMeta.builder().ownerName(OWNER_NAME).description(NAMESPACE_DESCRIPTION).build();
153+
154+
MARQUEZ_CLIENT.createNamespace(namespaceName, namespaceMeta);
155+
}
156+
157+
protected static DatasetId newDatasetIdWith(final String namespaceName) {
158+
return new DatasetId(namespaceName, newDatasetName().getValue());
159+
}
160+
161+
protected void createSource(String sourceName) {
162+
final SourceMeta sourceMeta =
163+
SourceMeta.builder()
164+
.type(DB_TABLE_SOURCE_TYPE)
165+
.connectionUrl(DB_TABLE_CONNECTION_URL)
166+
.description(DB_TABLE_SOURCE_DESCRIPTION)
167+
.build();
168+
MARQUEZ_CLIENT.createSource(sourceName, sourceMeta);
169+
}
170+
92171
@AfterAll
93172
public static void cleanUp() {
94173
MARQUEZ_APP.after();

api/src/test/java/marquez/api/TagResourceIntegrationTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import static org.assertj.core.api.Assertions.assertThat;
1111

1212
import java.util.Set;
13+
import marquez.client.models.Dataset;
1314
import marquez.client.models.Tag;
1415
import org.junit.jupiter.api.Test;
1516

1617
public class TagResourceIntegrationTest extends BaseResourceIntegrationTest {
18+
1719
@Test
1820
public void testApp_createTag() {
1921
// (1) List tags.
@@ -36,4 +38,28 @@ public void testApp_listTags() {
3638
// (2) Ensure tags 'PII', 'SENSITIVE' defined in 'config.test.yml' are present.
3739
assertThat(tags).contains(PII, SENSITIVE);
3840
}
41+
42+
@Test
43+
public void testApp_testDatasetTagDelete() {
44+
// Create Namespace
45+
createNamespace(NAMESPACE_NAME);
46+
// create a source
47+
createSource(DB_TABLE_SOURCE_NAME);
48+
// Create Dataset
49+
MARQUEZ_CLIENT.createDataset(NAMESPACE_NAME, DB_TABLE_NAME, DB_TABLE_META);
50+
51+
// Tag Dataset with TESTDATASETTAG tag
52+
Dataset taggedDataset =
53+
MARQUEZ_CLIENT.tagDatasetWith(NAMESPACE_NAME, DB_TABLE_NAME, "TESTDATASETTAG");
54+
assertThat(taggedDataset.getTags()).contains("TESTDATASETTAG");
55+
56+
// Test that the tag TESTDATASETTAG is deleted from the dataset
57+
Dataset taggedDeleteDataset =
58+
MARQUEZ_CLIENT.deleteDatasetTag(NAMESPACE_NAME, DB_TABLE_NAME, "TESTDATASETTAG");
59+
assertThat(taggedDeleteDataset.getTags()).doesNotContain("TESTDATASETTAG");
60+
// assert the number of tags should be 1
61+
assertThat(taggedDeleteDataset.getTags()).hasSize(1);
62+
// assert that only PII remains
63+
assertThat(taggedDeleteDataset.getTags()).containsExactly("PII");
64+
}
3965
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ public Dataset tagDatasetWith(
240240
return Dataset.fromJson(bodyAsJson);
241241
}
242242

243+
public Dataset deleteDatasetTag(
244+
@NonNull String namespaceName, @NonNull String datasetName, @NonNull String tagName) {
245+
final String bodyAsJson = http.delete(url.toDatasetTagUrl(namespaceName, datasetName, tagName));
246+
return Dataset.fromJson(bodyAsJson);
247+
}
248+
243249
public Dataset tagFieldWith(
244250
@NonNull String namespaceName,
245251
@NonNull String datasetName,

clients/java/src/test/java/marquez/client/MarquezClientTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,19 @@ public void testTagDataset() throws Exception {
989989
assertThat(dataset).isEqualTo(DB_TABLE);
990990
}
991991

992+
@Test
993+
public void testDeleteDatasetTag() throws Exception {
994+
final URL url =
995+
buildUrlFor(
996+
"/namespaces/%s/datasets/%s/tags/%s", NAMESPACE_NAME, DB_TABLE_NAME, "tag_name");
997+
998+
final String runAsJson = Utils.getMapper().writeValueAsString(DB_TABLE);
999+
when(http.delete(url)).thenReturn(runAsJson);
1000+
1001+
final Dataset dataset = client.deleteDatasetTag(NAMESPACE_NAME, DB_TABLE_NAME, "tag_name");
1002+
assertThat(dataset).isEqualTo(DB_TABLE);
1003+
}
1004+
9921005
@Test
9931006
public void testTagField() throws Exception {
9941007
final URL url =

0 commit comments

Comments
 (0)