Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit 9e3307a

Browse files
authored
feat: Cloud Bigtable Managed Backup Implementation (#305)
1 parent 195f36b commit 9e3307a

16 files changed

Lines changed: 2171 additions & 0 deletions

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java

Lines changed: 421 additions & 0 deletions
Large diffs are not rendered by default.

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/internal/NameUtil.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public class NameUtil {
3131
Pattern.compile("projects/([^/]+)/instances/([^/]+)/tables/([^/]+)");
3232
private static final Pattern LOCATION_PATTERN =
3333
Pattern.compile("projects/([^/]+)/locations/([^/]+)");
34+
private static final Pattern BACKUP_PATTERN =
35+
Pattern.compile("projects/([^/]+)/instances/([^/]+)/clusters/([^/]+)/backups/([^/]+)");
3436

3537
public static String formatProjectName(String projectId) {
3638
return "projects/" + projectId;
@@ -48,6 +50,11 @@ public static String formatLocationName(String projectId, String zone) {
4850
return formatProjectName(projectId) + "/locations/" + zone;
4951
}
5052

53+
public static String formatBackupName(
54+
String projectId, String instanceId, String clusterId, String backupId) {
55+
return formatClusterName(projectId, instanceId, clusterId) + "/backups/" + backupId;
56+
}
57+
5158
public static String extractTableIdFromTableName(String fullTableName) {
5259
Matcher matcher = TABLE_PATTERN.matcher(fullTableName);
5360
if (!matcher.matches()) {
@@ -56,6 +63,14 @@ public static String extractTableIdFromTableName(String fullTableName) {
5663
return matcher.group(3);
5764
}
5865

66+
public static String extractBackupIdFromBackupName(String fullBackupName) {
67+
Matcher matcher = BACKUP_PATTERN.matcher(fullBackupName);
68+
if (!matcher.matches()) {
69+
throw new IllegalArgumentException("Invalid backup name: " + fullBackupName);
70+
}
71+
return matcher.group(4);
72+
}
73+
5974
public static String extractZoneIdFromLocationName(String fullLocationName) {
6075
Matcher matcher = LOCATION_PATTERN.matcher(fullLocationName);
6176
if (!matcher.matches()) {
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.bigtable.admin.v2.models;
18+
19+
import com.google.api.core.InternalApi;
20+
import com.google.bigtable.admin.v2.BackupName;
21+
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
22+
import com.google.common.base.Objects;
23+
import com.google.common.base.Preconditions;
24+
import com.google.protobuf.util.Timestamps;
25+
import javax.annotation.Nonnull;
26+
import javax.annotation.Nullable;
27+
import org.threeten.bp.Instant;
28+
29+
/**
30+
* A backup lets you save a copy of a table's schema and data and restore the backup to a new table
31+
* at a later time.
32+
*/
33+
public class Backup {
34+
public enum State {
35+
/** Not specified. */
36+
STATE_UNSPECIFIED(com.google.bigtable.admin.v2.Backup.State.STATE_UNSPECIFIED),
37+
38+
/**
39+
* The pending backup is still being created. Operations on the backup may fail with
40+
* `FAILED_PRECONDITION` in this state.
41+
*/
42+
CREATING(com.google.bigtable.admin.v2.Backup.State.CREATING),
43+
/** The backup is complete and ready for use. */
44+
READY(com.google.bigtable.admin.v2.Backup.State.READY),
45+
46+
/** The state of the backup is not known by this client. Please upgrade your client. */
47+
UNRECOGNIZED(com.google.bigtable.admin.v2.Backup.State.UNRECOGNIZED);
48+
49+
private final com.google.bigtable.admin.v2.Backup.State proto;
50+
51+
State(com.google.bigtable.admin.v2.Backup.State proto) {
52+
this.proto = proto;
53+
}
54+
55+
/**
56+
* Wraps the protobuf. This method is considered an internal implementation detail and not meant
57+
* to be used by applications.
58+
*/
59+
@InternalApi
60+
public static Backup.State fromProto(com.google.bigtable.admin.v2.Backup.State proto) {
61+
for (Backup.State state : values()) {
62+
if (state.proto.equals(proto)) {
63+
return state;
64+
}
65+
}
66+
return STATE_UNSPECIFIED;
67+
}
68+
69+
/**
70+
* Creates the request protobuf. This method is considered an internal implementation detail and
71+
* not meant to be used by applications.
72+
*/
73+
@InternalApi
74+
public com.google.bigtable.admin.v2.Backup.State toProto() {
75+
return proto;
76+
}
77+
}
78+
79+
@Nonnull private final com.google.bigtable.admin.v2.Backup proto;
80+
@Nonnull private final String id;
81+
@Nonnull private final String instanceId;
82+
83+
@InternalApi
84+
public static Backup fromProto(@Nonnull com.google.bigtable.admin.v2.Backup proto) {
85+
return new Backup(proto);
86+
}
87+
88+
private Backup(@Nonnull com.google.bigtable.admin.v2.Backup proto) {
89+
Preconditions.checkNotNull(proto);
90+
Preconditions.checkArgument(!proto.getName().isEmpty(), "Name must be set");
91+
Preconditions.checkArgument(!proto.getSourceTable().isEmpty(), "Source table must be set");
92+
93+
BackupName name = BackupName.parse(proto.getName());
94+
this.id = name.getBackup();
95+
this.instanceId = name.getInstance();
96+
this.proto = proto;
97+
}
98+
99+
/** Get the ID of this backup. */
100+
public String getId() {
101+
return id;
102+
}
103+
104+
/** Get the source table ID from which the backup is created. */
105+
public String getSourceTableId() {
106+
return NameUtil.extractTableIdFromTableName(proto.getSourceTable());
107+
}
108+
109+
/** Get the instance ID where this backup is located. */
110+
public String getInstanceId() {
111+
return instanceId;
112+
}
113+
114+
/** Get the expire time of this backup. */
115+
public Instant getExpireTime() {
116+
return Instant.ofEpochMilli(Timestamps.toMillis(proto.getExpireTime()));
117+
}
118+
119+
/** Get the start time when this backup is taken. */
120+
public @Nullable Instant getStartTime() {
121+
if (proto.hasStartTime()) {
122+
return Instant.ofEpochMilli(Timestamps.toMillis(proto.getStartTime()));
123+
}
124+
return null;
125+
}
126+
127+
/** Get the end time when the creation of this backup has completed. */
128+
public @Nullable Instant getEndTime() {
129+
if (proto.hasEndTime()) {
130+
return Instant.ofEpochMilli(Timestamps.toMillis(proto.getEndTime()));
131+
}
132+
return null;
133+
}
134+
135+
/** Get the size of this backup. */
136+
public long getSizeBytes() {
137+
return proto.getSizeBytes();
138+
}
139+
140+
/** Get the state of this backup. */
141+
public State getState() {
142+
return State.fromProto(proto.getState());
143+
}
144+
145+
@Override
146+
public boolean equals(Object o) {
147+
if (this == o) {
148+
return true;
149+
}
150+
if (o == null || getClass() != o.getClass()) {
151+
return false;
152+
}
153+
Backup backup = (Backup) o;
154+
return Objects.equal(proto, backup.proto);
155+
}
156+
157+
@Override
158+
public int hashCode() {
159+
return Objects.hashCode(proto);
160+
}
161+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.bigtable.admin.v2.models;
17+
18+
import com.google.api.core.InternalApi;
19+
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
20+
import com.google.common.base.Objects;
21+
import com.google.common.base.Preconditions;
22+
import com.google.protobuf.util.Timestamps;
23+
import javax.annotation.Nonnull;
24+
import org.threeten.bp.Instant;
25+
26+
/** Fluent wrapper for {@link com.google.bigtable.admin.v2.CreateBackupRequest} */
27+
public final class CreateBackupRequest {
28+
private final com.google.bigtable.admin.v2.CreateBackupRequest.Builder requestBuilder =
29+
com.google.bigtable.admin.v2.CreateBackupRequest.newBuilder();
30+
private final String clusterId;
31+
private String sourceTableId;
32+
33+
public static CreateBackupRequest of(String clusterId, String backupId) {
34+
CreateBackupRequest request = new CreateBackupRequest(clusterId, backupId);
35+
return request;
36+
}
37+
38+
private CreateBackupRequest(String clusterId, String backupId) {
39+
Preconditions.checkNotNull(clusterId);
40+
Preconditions.checkNotNull(backupId);
41+
42+
requestBuilder.setBackupId(backupId);
43+
this.clusterId = clusterId;
44+
this.sourceTableId = null;
45+
}
46+
47+
public CreateBackupRequest setSourceTableId(String sourceTableId) {
48+
Preconditions.checkNotNull(sourceTableId);
49+
this.sourceTableId = sourceTableId;
50+
return this;
51+
}
52+
53+
public CreateBackupRequest setExpireTime(Instant expireTime) {
54+
Preconditions.checkNotNull(expireTime);
55+
requestBuilder
56+
.getBackupBuilder()
57+
.setExpireTime(Timestamps.fromMillis(expireTime.toEpochMilli()));
58+
return this;
59+
}
60+
61+
@Override
62+
public boolean equals(Object o) {
63+
if (this == o) {
64+
return true;
65+
}
66+
if (o == null || getClass() != o.getClass()) {
67+
return false;
68+
}
69+
CreateBackupRequest that = (CreateBackupRequest) o;
70+
return Objects.equal(requestBuilder.getBackupId(), that.requestBuilder.getBackupId())
71+
&& Objects.equal(clusterId, that.clusterId)
72+
&& Objects.equal(sourceTableId, that.sourceTableId);
73+
}
74+
75+
@Override
76+
public int hashCode() {
77+
return Objects.hashCode(requestBuilder.getBackupId(), clusterId, sourceTableId);
78+
}
79+
80+
@InternalApi
81+
public com.google.bigtable.admin.v2.CreateBackupRequest toProto(
82+
@Nonnull String projectId, @Nonnull String instanceId) {
83+
Preconditions.checkNotNull(projectId);
84+
Preconditions.checkNotNull(instanceId);
85+
86+
requestBuilder
87+
.getBackupBuilder()
88+
.setSourceTable(NameUtil.formatTableName(projectId, instanceId, sourceTableId));
89+
return requestBuilder
90+
.setParent(NameUtil.formatClusterName(projectId, instanceId, clusterId))
91+
.build();
92+
}
93+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.bigtable.admin.v2.models;
17+
18+
import com.google.api.core.InternalApi;
19+
import com.google.common.base.Preconditions;
20+
21+
/**
22+
* OptimizeRestoredTableOperationToken is a wrapper for the name of OptimizeRestoredTable operation.
23+
*/
24+
public class OptimizeRestoredTableOperationToken {
25+
private final String operationName;
26+
27+
@InternalApi
28+
public static OptimizeRestoredTableOperationToken of(String operationName) {
29+
return new OptimizeRestoredTableOperationToken(operationName);
30+
}
31+
32+
private OptimizeRestoredTableOperationToken(String operationName) {
33+
Preconditions.checkNotNull(operationName);
34+
Preconditions.checkState(!operationName.isEmpty());
35+
this.operationName = operationName;
36+
}
37+
38+
@InternalApi
39+
public String getOperationName() {
40+
return operationName;
41+
}
42+
}

0 commit comments

Comments
 (0)