-
Notifications
You must be signed in to change notification settings - Fork 134
feat(bigquery): support IAM conditions in datasets in Java client. #3602
Changes from 3 commits
826654f
a79baf3
7610a8f
001ed1c
15fc548
7babc4b
a17b6d9
fc6f203
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 |
|---|---|---|
|
|
@@ -21,6 +21,7 @@ | |
| import com.google.api.core.ApiFunction; | ||
| import com.google.api.services.bigquery.model.Dataset.Access; | ||
| import com.google.api.services.bigquery.model.DatasetAccessEntry; | ||
| import com.google.api.services.bigquery.model.Expr; | ||
| import com.google.cloud.StringEnumType; | ||
| import com.google.cloud.StringEnumValue; | ||
| import java.io.Serializable; | ||
|
|
@@ -41,6 +42,7 @@ public final class Acl implements Serializable { | |
|
|
||
| private final Entity entity; | ||
| private final Role role; | ||
| private final Expr condition; | ||
|
|
||
| /** | ||
| * Dataset roles supported by BigQuery. | ||
|
|
@@ -568,9 +570,77 @@ Access toPb() { | |
| } | ||
| } | ||
|
|
||
| /** Expr represents the conditional information related to dataset access policies. */ | ||
| public static final class Expr implements Serializable { | ||
| // Textual representation of an expression in Common Expression Language syntax. | ||
| private final String expression; | ||
| /** | ||
| * Optional. Title for the expression, i.e. a short string describing its purpose. This can be | ||
| * used e.g. in UIs which allow to enter the expression. | ||
| */ | ||
| private final String title; | ||
| /** | ||
| * Optional. Description of the expression. This is a longer text which describes the | ||
| * expression, e.g. when hovered over it in a UI. | ||
| */ | ||
| private final String description; | ||
| /** | ||
| * Optional. String indicating the location of the expression for error reporting, e.g. a file | ||
| * name and a position in the file. | ||
| */ | ||
| private final String location; | ||
|
|
||
| public Expr(String expression, String title, String description, String location) { | ||
|
PhongChuong marked this conversation as resolved.
|
||
| this.expression = expression; | ||
| this.title = title; | ||
| this.description = description; | ||
| this.location = location; | ||
| } | ||
|
|
||
| com.google.api.services.bigquery.model.Expr toPb() { | ||
| com.google.api.services.bigquery.model.Expr bqExpr = | ||
| new com.google.api.services.bigquery.model.Expr(); | ||
| bqExpr.setExpression(this.expression); | ||
| bqExpr.setTitle(this.title); | ||
| bqExpr.setDescription(this.description); | ||
| bqExpr.setLocation(this.location); | ||
| return bqExpr; | ||
| } | ||
|
|
||
| static Expr fromPb(com.google.api.services.bigquery.model.Expr bqExpr) { | ||
| return new Expr( | ||
| bqExpr.getExpression(), bqExpr.getTitle(), bqExpr.getDescription(), bqExpr.getLocation()); | ||
| } | ||
|
|
||
| @Override | ||
|
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. Include toString() as well as the normal methods like equals and hashcode?
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. Good point, updated to have toString() method. |
||
| public int hashCode() { | ||
| return Objects.hash(expression, title, description, location); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object obj) { | ||
| if (this == obj) { | ||
| return true; | ||
| } | ||
| if (obj == null || getClass() != obj.getClass()) { | ||
| return false; | ||
| } | ||
| final Expr other = (Expr) obj; | ||
| return Objects.equals(this.expression, other.expression) | ||
| && Objects.equals(this.title, other.title) | ||
| && Objects.equals(this.description, other.description) | ||
| && Objects.equals(this.location, other.location); | ||
| } | ||
| } | ||
|
|
||
| private Acl(Entity entity, Role role) { | ||
| this(entity, role, null); | ||
| } | ||
|
|
||
| private Acl(Entity entity, Role role, Expr condition) { | ||
| this.entity = checkNotNull(entity); | ||
| this.role = role; | ||
| this.condition = condition; | ||
| } | ||
|
|
||
| /** @return Returns the entity for this ACL. */ | ||
|
|
@@ -582,6 +652,10 @@ public Entity getEntity() { | |
| public Role getRole() { | ||
| return role; | ||
| } | ||
| /** @return Returns the condition specified by this ACL. */ | ||
| public Expr getCondition() { | ||
| return condition; | ||
| } | ||
|
|
||
| /** | ||
| * @return Returns an Acl object. | ||
|
|
@@ -592,6 +666,10 @@ public static Acl of(Entity entity, Role role) { | |
| return new Acl(entity, role); | ||
| } | ||
|
|
||
| public static Acl of(Entity entity, Role role, Expr condition) { | ||
| return new Acl(entity, role, condition); | ||
| } | ||
|
|
||
| /** | ||
| * @param datasetAclEntity | ||
| * @return Returns an Acl object for a datasetAclEntity. | ||
|
|
@@ -618,7 +696,7 @@ public static Acl of(Routine routine) { | |
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(entity, role); | ||
| return Objects.hash(entity, role, condition); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -635,19 +713,26 @@ public boolean equals(Object obj) { | |
| return false; | ||
| } | ||
| final Acl other = (Acl) obj; | ||
| return Objects.equals(this.entity, other.entity) && Objects.equals(this.role, other.role); | ||
| return Objects.equals(this.entity, other.entity) | ||
| && Objects.equals(this.role, other.role) | ||
| && Objects.equals(this.condition, other.condition); | ||
| } | ||
|
|
||
| Access toPb() { | ||
| Access accessPb = entity.toPb(); | ||
| if (role != null) { | ||
| accessPb.setRole(role.name()); | ||
| } | ||
| if (condition != null) { | ||
| accessPb.setCondition(condition.toPb()); | ||
| } | ||
| return accessPb; | ||
| } | ||
|
|
||
| static Acl fromPb(Access access) { | ||
| return Acl.of( | ||
| Entity.fromPb(access), access.getRole() != null ? Role.valueOf(access.getRole()) : null); | ||
| Entity.fromPb(access), | ||
| access.getRole() != null ? Role.valueOf(access.getRole()) : null, | ||
| access.getCondition() != null ? Expr.fromPb(access.getCondition()) : null); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -130,6 +130,21 @@ private void validateRPC() throws BigQueryException, IOException { | |
| public Dataset getDataset(String projectId, String datasetId, Map<Option, ?> options) { | ||
| try { | ||
| validateRPC(); | ||
| Integer accessPolicyVersion = null; | ||
|
PhongChuong marked this conversation as resolved.
Outdated
|
||
| for (Map.Entry<Option, ?> entry : options.entrySet()) { | ||
| if (entry.getKey() == Option.ACCESS_POLICY_VERSION && entry.getValue() != null) { | ||
| accessPolicyVersion = (Integer) entry.getValue(); | ||
| } | ||
| } | ||
| if (accessPolicyVersion != null) { | ||
| return bigquery | ||
|
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. nit: I worry here is if there's a divergence between this chain and the default execute(). Is it worth doing a single chain of builders with a conditional? Same with this pattern in the other RPCs (create, patch, etc).
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. Yes that approach seems cleaner. I updated the conditional to toggle only the access policy version instead of creating an entirely new RPC. |
||
| .datasets() | ||
| .get(projectId, datasetId) | ||
| .setFields(Option.FIELDS.getString(options)) | ||
| .setPrettyPrint(false) | ||
| .setAccessPolicyVersion(accessPolicyVersion) | ||
| .execute(); | ||
| } | ||
| return bigquery | ||
| .datasets() | ||
| .get(projectId, datasetId) | ||
|
|
@@ -174,6 +189,21 @@ public Tuple<String, Iterable<Dataset>> listDatasets(String projectId, Map<Optio | |
| public Dataset create(Dataset dataset, Map<Option, ?> options) { | ||
| try { | ||
| validateRPC(); | ||
| Integer accessPolicyVersion = null; | ||
|
whuffman36 marked this conversation as resolved.
Outdated
|
||
| for (Map.Entry<Option, ?> entry : options.entrySet()) { | ||
| if (entry.getKey() == Option.ACCESS_POLICY_VERSION && entry.getValue() != null) { | ||
| accessPolicyVersion = (Integer) entry.getValue(); | ||
| } | ||
| } | ||
| if (accessPolicyVersion != null) { | ||
| return bigquery | ||
| .datasets() | ||
| .insert(dataset.getDatasetReference().getProjectId(), dataset) | ||
| .setPrettyPrint(false) | ||
| .setFields(Option.FIELDS.getString(options)) | ||
| .setAccessPolicyVersion(accessPolicyVersion) | ||
| .execute(); | ||
| } | ||
| return bigquery | ||
| .datasets() | ||
| .insert(dataset.getDatasetReference().getProjectId(), dataset) | ||
|
|
@@ -276,7 +306,22 @@ public boolean deleteDataset(String projectId, String datasetId, Map<Option, ?> | |
| public Dataset patch(Dataset dataset, Map<Option, ?> options) { | ||
| try { | ||
| validateRPC(); | ||
| Integer accessPolicyVersion = null; | ||
|
whuffman36 marked this conversation as resolved.
Outdated
|
||
| for (Map.Entry<Option, ?> entry : options.entrySet()) { | ||
| if (entry.getKey() == Option.ACCESS_POLICY_VERSION && entry.getValue() != null) { | ||
| accessPolicyVersion = (Integer) entry.getValue(); | ||
| } | ||
| } | ||
| DatasetReference reference = dataset.getDatasetReference(); | ||
| if (accessPolicyVersion != null) { | ||
| return bigquery | ||
| .datasets() | ||
| .patch(reference.getProjectId(), reference.getDatasetId(), dataset) | ||
| .setPrettyPrint(false) | ||
| .setFields(Option.FIELDS.getString(options)) | ||
| .setAccessPolicyVersion(accessPolicyVersion) | ||
| .execute(); | ||
| } | ||
| return bigquery | ||
| .datasets() | ||
| .patch(reference.getProjectId(), reference.getDatasetId(), dataset) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.