-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Add Data Catalog createEntry quickstart samples and tests. #1731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
4bc1c34
9ced693
08d40cf
3a1460b
a896ec3
f6a4c02
0f15c98
b0981ab
19c9a25
573074f
0f51ac9
63d7523
90948e5
1d5a089
350f6fa
71c4af2
11646ea
faca3b7
0f68bd0
fe434f3
8993ac4
594821e
9684187
420577d
db3c8a9
4760778
283634d
09d1748
1e086cf
c434a8c
e986d0b
0c13f44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| /* | ||
| * Copyright 2019 Google Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package com.example.datacatalog; | ||
|
|
||
| // [START datacatalog_create_fileset_quickstart_tag] | ||
|
|
||
| import com.google.api.gax.rpc.AlreadyExistsException; | ||
| import com.google.api.gax.rpc.NotFoundException; | ||
| import com.google.api.gax.rpc.PermissionDeniedException; | ||
| import com.google.cloud.datacatalog.ColumnSchema; | ||
| import com.google.cloud.datacatalog.CreateEntryGroupRequest; | ||
| import com.google.cloud.datacatalog.CreateEntryRequest; | ||
| import com.google.cloud.datacatalog.Entry; | ||
| import com.google.cloud.datacatalog.EntryGroup; | ||
| import com.google.cloud.datacatalog.EntryGroupName; | ||
| import com.google.cloud.datacatalog.EntryName; | ||
| import com.google.cloud.datacatalog.EntryType; | ||
| import com.google.cloud.datacatalog.GcsFilesetSpec; | ||
| import com.google.cloud.datacatalog.LocationName; | ||
| import com.google.cloud.datacatalog.Schema; | ||
| import com.google.cloud.datacatalog.v1beta1.DataCatalogClient; | ||
| import java.io.IOException; | ||
|
|
||
| public class CreateFilesetEntryQuickStart { | ||
|
|
||
| public static void createEntry() { | ||
| // TODO(developer): Replace these variables before running the sample. | ||
| String projectId = "my-project-id"; | ||
| String entryGroupId = "fileset_entry_group"; | ||
| String entryId = "fileset_entry_id"; | ||
| createEntry(projectId, entryGroupId, entryId); | ||
| } | ||
|
|
||
| // Create Fileset Entry. | ||
| public static void createEntry(String projectId, String entryGroupId, String entryId) { | ||
| // Currently, Data Catalog stores metadata in the us-central1 region. | ||
| String location = "us-central1"; | ||
|
|
||
| // Initialize client that will be used to send requests. This client only needs to be created | ||
| // once, and can be reused for multiple requests. After completing all of your requests, call | ||
| // the "close" method on the client to safely clean up any remaining background resources. | ||
| try (DataCatalogClient dataCatalogClient = DataCatalogClient.create()) { | ||
|
|
||
| // 1. Environment cleanup: delete pre-existing data. | ||
| // Delete any pre-existing Entry with the same name | ||
| // that will be used in step 3. | ||
| try { | ||
| dataCatalogClient.deleteEntry( | ||
| EntryName.of(projectId, location, entryGroupId, entryId).toString()); | ||
| } catch (PermissionDeniedException | NotFoundException e) { | ||
| // PermissionDeniedException or NotFoundException are thrown if | ||
| // Entry does not exist. | ||
| System.out.println("Entry does not exist."); | ||
| } | ||
|
|
||
| // Delete any pre-existing Entry Group with the same name | ||
| // that will be used in step 2. | ||
| try { | ||
| dataCatalogClient.deleteEntryGroup( | ||
| EntryGroupName.of(projectId, location, entryGroupId).toString()); | ||
| } catch (PermissionDeniedException | NotFoundException e) { | ||
| // PermissionDeniedException or NotFoundException are thrown if | ||
| // Entry Group does not exist. | ||
| System.out.println("Entry Group does not exist."); | ||
| } | ||
|
|
||
| // 2. Create an Entry Group. | ||
| // Construct the EntryGroup for the EntryGroup request. | ||
| EntryGroup entryGroup = | ||
| EntryGroup.newBuilder() | ||
| .setDisplayName("My Fileset Entry Group") | ||
| .setDescription("This Entry Group consists of ....") | ||
| .build(); | ||
|
|
||
| // Construct the EntryGroup request to be sent by the client. | ||
| CreateEntryGroupRequest entryGroupRequest = | ||
| CreateEntryGroupRequest.newBuilder() | ||
| .setParent(LocationName.of(projectId, location).toString()) | ||
| .setEntryGroupId(entryGroupId) | ||
| .setEntryGroup(entryGroup) | ||
| .build(); | ||
|
|
||
| // Use the client to send the API request. | ||
| EntryGroup entryGroupResponse = dataCatalogClient.createEntryGroup(entryGroupRequest); | ||
|
|
||
| System.out.printf("\nEntry Group created with name: %s\n", entryGroupResponse.getName()); | ||
|
|
||
| // 3. Create a Fileset Entry. | ||
| // Construct the Entry for the Entry request. | ||
| Entry entry = | ||
| Entry.newBuilder() | ||
| .setDisplayName("My Fileset") | ||
| .setDescription("This fileset consists of ....") | ||
| .setGcsFilesetSpec( | ||
| GcsFilesetSpec.newBuilder().addFilePatterns("gs://my_bucket/*").build()) | ||
| .setSchema( | ||
| Schema.newBuilder() | ||
| .addColumns( | ||
| ColumnSchema.newBuilder() | ||
| .setColumn("first_name") | ||
| .setDescription("First name") | ||
| .setMode("REQUIRED") | ||
| .setType("STRING") | ||
| .build()) | ||
| .addColumns( | ||
| ColumnSchema.newBuilder() | ||
| .setColumn("last_name") | ||
| .setDescription("Last name") | ||
| .setMode("REQUIRED") | ||
| .setType("STRING") | ||
| .build()) | ||
| .addColumns( | ||
| ColumnSchema.newBuilder() | ||
| .setColumn("addresses") | ||
| .setDescription("Addresses") | ||
| .setMode("REPEATED") | ||
| .setType("RECORD") | ||
| .addSubcolumns( | ||
| ColumnSchema.newBuilder() | ||
| .setColumn("city") | ||
| .setDescription("City") | ||
| .setMode("NULLABLE") | ||
| .setType("STRING") | ||
| .build()) | ||
| .addSubcolumns( | ||
| ColumnSchema.newBuilder() | ||
| .setColumn("state") | ||
| .setDescription("State") | ||
| .setMode("NULLABLE") | ||
| .setType("STRING") | ||
| .build()) | ||
| .build()) | ||
| .build()) | ||
| .setType(EntryType.FILESET) | ||
| .build(); | ||
|
|
||
| // Construct the Entry request to be sent by the client. | ||
| CreateEntryRequest entryRequest = | ||
| CreateEntryRequest.newBuilder() | ||
| .setParent(entryGroupResponse.getName()) | ||
| .setEntryId(entryId) | ||
| .setEntry(entry) | ||
| .build(); | ||
|
|
||
| // Use the client to send the API request. | ||
| Entry entryResponse = dataCatalogClient.createEntry(entryRequest); | ||
|
|
||
| System.out.printf("\nEntry created with name: %s\n", entryResponse.getName()); | ||
| } catch (AlreadyExistsException | IOException e) { | ||
| // AlreadyExistsException's are thrown if EntryGroup or Entry already exists. | ||
| // IOException's are thrown when unable to create the DataCatalogClient, | ||
| // for example an invalid Service Account path. | ||
| System.out.println("Error in create entry process:\n" + e.toString()); | ||
| } | ||
| } | ||
| } | ||
| // [END datacatalog_create_fileset_quickstart_tag] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,12 +17,15 @@ | |
| package com.example.datacatalog; | ||
|
|
||
| import static org.junit.Assert.assertThat; | ||
| import static org.junit.Assert.fail; | ||
|
|
||
| import com.google.cloud.datacatalog.EntryGroupName; | ||
| import com.google.cloud.datacatalog.EntryName; | ||
| import com.google.cloud.datacatalog.v1beta1.DataCatalogClient; | ||
| import java.io.ByteArrayOutputStream; | ||
| import java.io.PrintStream; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.UUID; | ||
| import org.hamcrest.CoreMatchers; | ||
| import org.junit.After; | ||
|
|
@@ -32,21 +35,21 @@ | |
| import org.junit.runner.RunWith; | ||
| import org.junit.runners.JUnit4; | ||
|
|
||
| /** Integration (system) tests for {@link CreateFilesetEntry} and {@link CreateEntryGroup}. */ | ||
| /** | ||
| * Integration (system) tests for {@link CreateFilesetEntry} and {@link CreateEntryGroup} and {@link | ||
| * CreateFilesetEntryQuickStart}. | ||
| */ | ||
| @RunWith(JUnit4.class) | ||
| public class CreateEntryTests { | ||
|
|
||
| private ByteArrayOutputStream bout; | ||
|
|
||
| private static String ENTRY_GROUP_ID_NO_CHILDREN = | ||
| "entry_group_no_children_" + UUID.randomUUID().toString().substring(0, 8); | ||
| private static String PARENT_ENTRY_GROUP_ID = | ||
| "fileset_entry_group_parent_" + UUID.randomUUID().toString().substring(0, 8); | ||
| private static String ENTRY_ID = | ||
| "fileset_entry_id_" + UUID.randomUUID().toString().substring(0, 8); | ||
| private static String LOCATION = "us-central1"; | ||
| private static String PROJECT_ID = System.getenv().get("GOOGLE_CLOUD_PROJECT"); | ||
|
|
||
| private static List<String> entryGroupsPendingDeletion = new ArrayList<>(); | ||
| private static List<String> entriesPendingDeletion = new ArrayList<>(); | ||
|
|
||
| @Before | ||
| public void setUp() { | ||
| bout = new ByteArrayOutputStream(); | ||
|
|
@@ -62,45 +65,93 @@ public void tearDown() { | |
| @AfterClass | ||
| public static void tearDownClass() { | ||
| try (DataCatalogClient dataCatalogClient = DataCatalogClient.create()) { | ||
| dataCatalogClient.deleteEntryGroup( | ||
| EntryGroupName.of(PROJECT_ID, LOCATION, ENTRY_GROUP_ID_NO_CHILDREN).toString()); | ||
|
|
||
| dataCatalogClient.deleteEntry( | ||
| EntryName.of(PROJECT_ID, LOCATION, PARENT_ENTRY_GROUP_ID, ENTRY_ID).toString()); | ||
| dataCatalogClient.deleteEntryGroup( | ||
| EntryGroupName.of(PROJECT_ID, LOCATION, PARENT_ENTRY_GROUP_ID).toString()); | ||
| // Must delete Entries before deleting the Entry Group. | ||
| if (entriesPendingDeletion.isEmpty() || entryGroupsPendingDeletion.isEmpty()) { | ||
| fail("Something went wrong, no entries were generated"); | ||
| } | ||
|
|
||
| for (String entryName : entriesPendingDeletion) { | ||
| dataCatalogClient.deleteEntry(entryName); | ||
| } | ||
|
|
||
| for (String entryGroupName : entryGroupsPendingDeletion) { | ||
| dataCatalogClient.deleteEntryGroup(entryGroupName); | ||
| } | ||
| } catch (Exception e) { | ||
| System.out.println("Error in cleaning up test data:\n" + e.toString()); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void testCreateFilesetEntry() { | ||
| String entryGroupId = "fileset_entry_group_parent_" + getUuid8Chars(); | ||
| String entryId = "fileset_entry_id_" + getUuid8Chars(); | ||
|
|
||
| // Must create a Entry Group before creating the entry. | ||
| CreateEntryGroup.createEntryGroup(PROJECT_ID, PARENT_ENTRY_GROUP_ID); | ||
| CreateFilesetEntry.createEntry(PROJECT_ID, PARENT_ENTRY_GROUP_ID, ENTRY_ID); | ||
| CreateEntryGroup.createEntryGroup(PROJECT_ID, entryGroupId); | ||
| CreateFilesetEntry.createEntry(PROJECT_ID, entryGroupId, entryId); | ||
|
|
||
| // Store names for clean up on teardown | ||
| String expectedEntryGroupName = | ||
| EntryGroupName.of(PROJECT_ID, LOCATION, entryGroupId).toString(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI: I think these helpers are being deprecated. At least, they were deprecated in Python (googleapis/gapic-generator#3012) and the same reasoning applies to the Java generator (it's not possible with new proto annotations for configuring the generator).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you know the recommended way?
Thanks
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At least in Python (2) is recommended, as the resource builders are going away there. I haven't seen any discussion about it outside of Python, though. I don't know why, as the same configuration changes affect all languages.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, it makes sense going that way if this configuration will affect all languages...
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK, they aren't going away for Java. They are generally preferred to manually formatting the string.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tswast WDYT can we keep the helpers?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have doubts that they will actually stay in Java, based on my conversations with Luke on the ACtools team. I'll check with him if the resource helper deprecation is supposed to affect more than just Python.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, will wait for your confirmation.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can proceed with using the resource builders. I misunderstood the reasoning for removal in Python.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so AFAIK the PR is ready to be merged, @tswast are you able to review it and merge if everything is ok? |
||
| entryGroupsPendingDeletion.add(expectedEntryGroupName); | ||
|
|
||
| String expectedEntryName = EntryName.of(PROJECT_ID, LOCATION, entryGroupId, entryId).toString(); | ||
| entriesPendingDeletion.add(expectedEntryName); | ||
|
|
||
| String output = bout.toString(); | ||
|
|
||
| String entryTemplate = | ||
| "Entry created with name: projects/%s/locations/us-central1/entryGroups/%s/entries/%s"; | ||
| String entryTemplate = "Entry created with name: %s"; | ||
| assertThat( | ||
| output, | ||
| CoreMatchers.containsString( | ||
| String.format(entryTemplate, PROJECT_ID, PARENT_ENTRY_GROUP_ID, ENTRY_ID))); | ||
| output, CoreMatchers.containsString(String.format(entryTemplate, expectedEntryName))); | ||
| } | ||
|
|
||
| @Test | ||
| public void testCreateEntryGroup() { | ||
| CreateEntryGroup.createEntryGroup(PROJECT_ID, ENTRY_GROUP_ID_NO_CHILDREN); | ||
| String entryGroupId = "entry_group_no_children_" + getUuid8Chars(); | ||
|
|
||
| CreateEntryGroup.createEntryGroup(PROJECT_ID, entryGroupId); | ||
|
|
||
| // Store names for clean up on teardown | ||
| String expectedEntryGroupName = | ||
| EntryGroupName.of(PROJECT_ID, LOCATION, entryGroupId).toString(); | ||
| entryGroupsPendingDeletion.add(expectedEntryGroupName); | ||
|
|
||
| String output = bout.toString(); | ||
|
|
||
| String entryGroupTemplate = | ||
| "Entry Group created with name: projects/%s/locations/us-central1/entryGroups/%s"; | ||
| String entryGroupTemplate = "Entry Group created with name: %s"; | ||
| assertThat( | ||
| output, | ||
| CoreMatchers.containsString( | ||
| String.format(entryGroupTemplate, PROJECT_ID, ENTRY_GROUP_ID_NO_CHILDREN))); | ||
| CoreMatchers.containsString(String.format(entryGroupTemplate, expectedEntryGroupName))); | ||
| } | ||
|
|
||
| @Test | ||
| public void testCreateEntryQuickStart() { | ||
| String entryGroupId = "fileset_entry_group_parent_" + getUuid8Chars(); | ||
| String entryId = "fileset_entry_id_" + getUuid8Chars(); | ||
|
|
||
| CreateFilesetEntryQuickStart.createEntry(PROJECT_ID, entryGroupId, entryId); | ||
|
|
||
| // Store names for clean up on teardown | ||
| String expectedEntryGroupName = | ||
| EntryGroupName.of(PROJECT_ID, LOCATION, entryGroupId).toString(); | ||
| entryGroupsPendingDeletion.add(expectedEntryGroupName); | ||
|
|
||
| String expectedEntryName = EntryName.of(PROJECT_ID, LOCATION, entryGroupId, entryId).toString(); | ||
| entriesPendingDeletion.add(expectedEntryName); | ||
|
|
||
| String output = bout.toString(); | ||
|
|
||
| String entryTemplate = "Entry created with name: %s"; | ||
| String entryGroupTemplate = "Entry Group created with name: %s"; | ||
| assertThat( | ||
| output, | ||
| CoreMatchers.containsString(String.format(entryGroupTemplate, expectedEntryGroupName))); | ||
| assertThat( | ||
| output, CoreMatchers.containsString(String.format(entryTemplate, expectedEntryName))); | ||
| } | ||
|
|
||
| private String getUuid8Chars() { | ||
| return UUID.randomUUID().toString().substring(0, 8); | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.