google-cloud-spanner 3.55.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google/cloud/spanner.py +47 -0
- google/cloud/spanner_admin_database_v1/__init__.py +146 -0
- google/cloud/spanner_admin_database_v1/gapic_metadata.json +418 -0
- google/cloud/spanner_admin_database_v1/gapic_version.py +16 -0
- google/cloud/spanner_admin_database_v1/py.typed +2 -0
- google/cloud/spanner_admin_database_v1/services/__init__.py +15 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py +22 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py +4097 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/client.py +4602 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py +989 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py +38 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py +820 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py +1303 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py +1688 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py +6512 -0
- google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest_base.py +1650 -0
- google/cloud/spanner_admin_database_v1/types/__init__.py +144 -0
- google/cloud/spanner_admin_database_v1/types/backup.py +1106 -0
- google/cloud/spanner_admin_database_v1/types/backup_schedule.py +369 -0
- google/cloud/spanner_admin_database_v1/types/common.py +180 -0
- google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py +1303 -0
- google/cloud/spanner_admin_instance_v1/__init__.py +110 -0
- google/cloud/spanner_admin_instance_v1/gapic_metadata.json +343 -0
- google/cloud/spanner_admin_instance_v1/gapic_version.py +16 -0
- google/cloud/spanner_admin_instance_v1/py.typed +2 -0
- google/cloud/spanner_admin_instance_v1/services/__init__.py +15 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py +22 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py +3466 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py +3881 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py +856 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py +38 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py +545 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py +1347 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py +1539 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py +4834 -0
- google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest_base.py +1198 -0
- google/cloud/spanner_admin_instance_v1/types/__init__.py +104 -0
- google/cloud/spanner_admin_instance_v1/types/common.py +99 -0
- google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py +2375 -0
- google/cloud/spanner_dbapi/__init__.py +93 -0
- google/cloud/spanner_dbapi/_helpers.py +113 -0
- google/cloud/spanner_dbapi/batch_dml_executor.py +135 -0
- google/cloud/spanner_dbapi/checksum.py +80 -0
- google/cloud/spanner_dbapi/client_side_statement_executor.py +140 -0
- google/cloud/spanner_dbapi/client_side_statement_parser.py +106 -0
- google/cloud/spanner_dbapi/connection.py +818 -0
- google/cloud/spanner_dbapi/cursor.py +609 -0
- google/cloud/spanner_dbapi/exceptions.py +172 -0
- google/cloud/spanner_dbapi/parse_utils.py +392 -0
- google/cloud/spanner_dbapi/parsed_statement.py +63 -0
- google/cloud/spanner_dbapi/parser.py +258 -0
- google/cloud/spanner_dbapi/partition_helper.py +41 -0
- google/cloud/spanner_dbapi/transaction_helper.py +294 -0
- google/cloud/spanner_dbapi/types.py +106 -0
- google/cloud/spanner_dbapi/utils.py +147 -0
- google/cloud/spanner_dbapi/version.py +20 -0
- google/cloud/spanner_v1/__init__.py +154 -0
- google/cloud/spanner_v1/_helpers.py +751 -0
- google/cloud/spanner_v1/_opentelemetry_tracing.py +165 -0
- google/cloud/spanner_v1/backup.py +397 -0
- google/cloud/spanner_v1/batch.py +433 -0
- google/cloud/spanner_v1/client.py +538 -0
- google/cloud/spanner_v1/data_types.py +350 -0
- google/cloud/spanner_v1/database.py +1968 -0
- google/cloud/spanner_v1/database_sessions_manager.py +249 -0
- google/cloud/spanner_v1/gapic_metadata.json +268 -0
- google/cloud/spanner_v1/gapic_version.py +16 -0
- google/cloud/spanner_v1/instance.py +735 -0
- google/cloud/spanner_v1/keyset.py +193 -0
- google/cloud/spanner_v1/merged_result_set.py +146 -0
- google/cloud/spanner_v1/metrics/constants.py +71 -0
- google/cloud/spanner_v1/metrics/metrics_capture.py +75 -0
- google/cloud/spanner_v1/metrics/metrics_exporter.py +384 -0
- google/cloud/spanner_v1/metrics/metrics_interceptor.py +156 -0
- google/cloud/spanner_v1/metrics/metrics_tracer.py +588 -0
- google/cloud/spanner_v1/metrics/metrics_tracer_factory.py +328 -0
- google/cloud/spanner_v1/metrics/spanner_metrics_tracer_factory.py +172 -0
- google/cloud/spanner_v1/param_types.py +110 -0
- google/cloud/spanner_v1/pool.py +813 -0
- google/cloud/spanner_v1/py.typed +2 -0
- google/cloud/spanner_v1/request_id_header.py +64 -0
- google/cloud/spanner_v1/services/__init__.py +15 -0
- google/cloud/spanner_v1/services/spanner/__init__.py +22 -0
- google/cloud/spanner_v1/services/spanner/async_client.py +2205 -0
- google/cloud/spanner_v1/services/spanner/client.py +2624 -0
- google/cloud/spanner_v1/services/spanner/pagers.py +196 -0
- google/cloud/spanner_v1/services/spanner/transports/__init__.py +38 -0
- google/cloud/spanner_v1/services/spanner/transports/base.py +520 -0
- google/cloud/spanner_v1/services/spanner/transports/grpc.py +911 -0
- google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py +1144 -0
- google/cloud/spanner_v1/services/spanner/transports/rest.py +3468 -0
- google/cloud/spanner_v1/services/spanner/transports/rest_base.py +981 -0
- google/cloud/spanner_v1/session.py +631 -0
- google/cloud/spanner_v1/session_options.py +133 -0
- google/cloud/spanner_v1/snapshot.py +1057 -0
- google/cloud/spanner_v1/streamed.py +402 -0
- google/cloud/spanner_v1/table.py +181 -0
- google/cloud/spanner_v1/testing/__init__.py +0 -0
- google/cloud/spanner_v1/testing/database_test.py +121 -0
- google/cloud/spanner_v1/testing/interceptors.py +118 -0
- google/cloud/spanner_v1/testing/mock_database_admin.py +38 -0
- google/cloud/spanner_v1/testing/mock_spanner.py +261 -0
- google/cloud/spanner_v1/testing/spanner_database_admin_pb2_grpc.py +1267 -0
- google/cloud/spanner_v1/testing/spanner_pb2_grpc.py +882 -0
- google/cloud/spanner_v1/transaction.py +747 -0
- google/cloud/spanner_v1/types/__init__.py +118 -0
- google/cloud/spanner_v1/types/commit_response.py +94 -0
- google/cloud/spanner_v1/types/keys.py +248 -0
- google/cloud/spanner_v1/types/mutation.py +201 -0
- google/cloud/spanner_v1/types/query_plan.py +220 -0
- google/cloud/spanner_v1/types/result_set.py +379 -0
- google/cloud/spanner_v1/types/spanner.py +1815 -0
- google/cloud/spanner_v1/types/transaction.py +818 -0
- google/cloud/spanner_v1/types/type.py +288 -0
- google_cloud_spanner-3.55.0.dist-info/LICENSE +202 -0
- google_cloud_spanner-3.55.0.dist-info/METADATA +318 -0
- google_cloud_spanner-3.55.0.dist-info/RECORD +119 -0
- google_cloud_spanner-3.55.0.dist-info/WHEEL +5 -0
- google_cloud_spanner-3.55.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Copyright 2020 Google LLC All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Manages OpenTelemetry trace creation and handling"""
|
|
16
|
+
|
|
17
|
+
from contextlib import contextmanager
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
import os
|
|
20
|
+
|
|
21
|
+
from google.cloud.spanner_v1 import SpannerClient
|
|
22
|
+
from google.cloud.spanner_v1 import gapic_version
|
|
23
|
+
from google.cloud.spanner_v1._helpers import (
|
|
24
|
+
_metadata_with_span_context,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
from opentelemetry import trace
|
|
29
|
+
from opentelemetry.trace.status import Status, StatusCode
|
|
30
|
+
from opentelemetry.semconv.attributes.otel_attributes import (
|
|
31
|
+
OTEL_SCOPE_NAME,
|
|
32
|
+
OTEL_SCOPE_VERSION,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
HAS_OPENTELEMETRY_INSTALLED = True
|
|
36
|
+
except ImportError:
|
|
37
|
+
HAS_OPENTELEMETRY_INSTALLED = False
|
|
38
|
+
|
|
39
|
+
from google.cloud.spanner_v1.metrics.metrics_capture import MetricsCapture
|
|
40
|
+
|
|
41
|
+
TRACER_NAME = "cloud.google.com/python/spanner"
|
|
42
|
+
TRACER_VERSION = gapic_version.__version__
|
|
43
|
+
extended_tracing_globally_disabled = (
|
|
44
|
+
os.getenv("SPANNER_ENABLE_EXTENDED_TRACING", "").lower() == "false"
|
|
45
|
+
)
|
|
46
|
+
end_to_end_tracing_globally_enabled = (
|
|
47
|
+
os.getenv("SPANNER_ENABLE_END_TO_END_TRACING", "").lower() == "true"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_tracer(tracer_provider=None):
|
|
52
|
+
"""
|
|
53
|
+
get_tracer is a utility to unify and simplify retrieval of the tracer, without
|
|
54
|
+
leaking implementation details given that retrieving a tracer requires providing
|
|
55
|
+
the full qualified library name and version.
|
|
56
|
+
When the tracer_provider is set, it'll retrieve the tracer from it, otherwise
|
|
57
|
+
it'll fall back to the global tracer provider and use this library's specific semantics.
|
|
58
|
+
"""
|
|
59
|
+
if not tracer_provider:
|
|
60
|
+
# Acquire the global tracer provider.
|
|
61
|
+
tracer_provider = trace.get_tracer_provider()
|
|
62
|
+
|
|
63
|
+
return tracer_provider.get_tracer(TRACER_NAME, TRACER_VERSION)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@contextmanager
|
|
67
|
+
def trace_call(
|
|
68
|
+
name, session=None, extra_attributes=None, observability_options=None, metadata=None
|
|
69
|
+
):
|
|
70
|
+
if session:
|
|
71
|
+
session._last_use_time = datetime.now()
|
|
72
|
+
|
|
73
|
+
if not (HAS_OPENTELEMETRY_INSTALLED and name):
|
|
74
|
+
# Empty context manager. Users will have to check if the generated value is None or a span
|
|
75
|
+
yield None
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
tracer_provider = None
|
|
79
|
+
|
|
80
|
+
# By default enable_extended_tracing=True because in a bid to minimize
|
|
81
|
+
# breaking changes and preserve legacy behavior, we are keeping it turned
|
|
82
|
+
# on by default.
|
|
83
|
+
enable_extended_tracing = True
|
|
84
|
+
|
|
85
|
+
enable_end_to_end_tracing = False
|
|
86
|
+
|
|
87
|
+
db_name = ""
|
|
88
|
+
if session and getattr(session, "_database", None):
|
|
89
|
+
db_name = session._database.name
|
|
90
|
+
|
|
91
|
+
if isinstance(observability_options, dict): # Avoid false positives with mock.Mock
|
|
92
|
+
tracer_provider = observability_options.get("tracer_provider", None)
|
|
93
|
+
enable_extended_tracing = observability_options.get(
|
|
94
|
+
"enable_extended_tracing", enable_extended_tracing
|
|
95
|
+
)
|
|
96
|
+
enable_end_to_end_tracing = observability_options.get(
|
|
97
|
+
"enable_end_to_end_tracing", enable_end_to_end_tracing
|
|
98
|
+
)
|
|
99
|
+
db_name = observability_options.get("db_name", db_name)
|
|
100
|
+
|
|
101
|
+
tracer = get_tracer(tracer_provider)
|
|
102
|
+
|
|
103
|
+
# Set base attributes that we know for every trace created
|
|
104
|
+
attributes = {
|
|
105
|
+
"db.type": "spanner",
|
|
106
|
+
"db.url": SpannerClient.DEFAULT_ENDPOINT,
|
|
107
|
+
"db.instance": db_name,
|
|
108
|
+
"net.host.name": SpannerClient.DEFAULT_ENDPOINT,
|
|
109
|
+
OTEL_SCOPE_NAME: TRACER_NAME,
|
|
110
|
+
OTEL_SCOPE_VERSION: TRACER_VERSION,
|
|
111
|
+
# Standard GCP attributes for OTel, attributes are used for internal purpose and are subjected to change
|
|
112
|
+
"gcp.client.service": "spanner",
|
|
113
|
+
"gcp.client.version": TRACER_VERSION,
|
|
114
|
+
"gcp.client.repo": "googleapis/python-spanner",
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if extra_attributes:
|
|
118
|
+
attributes.update(extra_attributes)
|
|
119
|
+
|
|
120
|
+
if extended_tracing_globally_disabled:
|
|
121
|
+
enable_extended_tracing = False
|
|
122
|
+
|
|
123
|
+
if not enable_extended_tracing:
|
|
124
|
+
attributes.pop("db.statement", False)
|
|
125
|
+
|
|
126
|
+
if end_to_end_tracing_globally_enabled:
|
|
127
|
+
enable_end_to_end_tracing = True
|
|
128
|
+
|
|
129
|
+
with tracer.start_as_current_span(
|
|
130
|
+
name, kind=trace.SpanKind.CLIENT, attributes=attributes
|
|
131
|
+
) as span:
|
|
132
|
+
with MetricsCapture():
|
|
133
|
+
try:
|
|
134
|
+
if enable_end_to_end_tracing:
|
|
135
|
+
_metadata_with_span_context(metadata)
|
|
136
|
+
yield span
|
|
137
|
+
except Exception as error:
|
|
138
|
+
span.set_status(Status(StatusCode.ERROR, str(error)))
|
|
139
|
+
# OpenTelemetry-Python imposes invoking span.record_exception on __exit__
|
|
140
|
+
# on any exception. We should file a bug later on with them to only
|
|
141
|
+
# invoke .record_exception if not already invoked, hence we should not
|
|
142
|
+
# invoke .record_exception on our own else we shall have 2 exceptions.
|
|
143
|
+
raise
|
|
144
|
+
else:
|
|
145
|
+
# All spans still have set_status available even if for example
|
|
146
|
+
# NonRecordingSpan doesn't have "_status".
|
|
147
|
+
absent_span_status = getattr(span, "_status", None) is None
|
|
148
|
+
if absent_span_status or span._status.status_code == StatusCode.UNSET:
|
|
149
|
+
# OpenTelemetry-Python only allows a status change
|
|
150
|
+
# if the current code is UNSET or ERROR. At the end
|
|
151
|
+
# of the generator's consumption, only set it to OK
|
|
152
|
+
# it wasn't previously set otherwise.
|
|
153
|
+
# https://github.com/googleapis/python-spanner/issues/1246
|
|
154
|
+
span.set_status(Status(StatusCode.OK))
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def get_current_span():
|
|
158
|
+
if not HAS_OPENTELEMETRY_INSTALLED:
|
|
159
|
+
return None
|
|
160
|
+
return trace.get_current_span()
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def add_span_event(span, event_name, event_attributes=None):
|
|
164
|
+
if span:
|
|
165
|
+
span.add_event(event_name, event_attributes)
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# Copyright 2020 Google LLC All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""User friendly container for Cloud Spanner Backup."""
|
|
16
|
+
|
|
17
|
+
import re
|
|
18
|
+
|
|
19
|
+
from google.cloud.exceptions import NotFound
|
|
20
|
+
|
|
21
|
+
from google.cloud.spanner_admin_database_v1 import Backup as BackupPB
|
|
22
|
+
from google.cloud.spanner_admin_database_v1 import CreateBackupEncryptionConfig
|
|
23
|
+
from google.cloud.spanner_admin_database_v1 import CreateBackupRequest
|
|
24
|
+
from google.cloud.spanner_admin_database_v1 import CopyBackupEncryptionConfig
|
|
25
|
+
from google.cloud.spanner_admin_database_v1 import CopyBackupRequest
|
|
26
|
+
from google.cloud.spanner_v1._helpers import _metadata_with_prefix
|
|
27
|
+
|
|
28
|
+
_BACKUP_NAME_RE = re.compile(
|
|
29
|
+
r"^projects/(?P<project>[^/]+)/"
|
|
30
|
+
r"instances/(?P<instance_id>[a-z][-a-z0-9]*)/"
|
|
31
|
+
r"backups/(?P<backup_id>[a-z][a-z0-9_\-]*[a-z0-9])$"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Backup(object):
|
|
36
|
+
"""Representation of a Cloud Spanner Backup.
|
|
37
|
+
|
|
38
|
+
We can use a :class`Backup` to:
|
|
39
|
+
|
|
40
|
+
* :meth:`create` the backup
|
|
41
|
+
* :meth:`update` the backup
|
|
42
|
+
* :meth:`delete` the backup
|
|
43
|
+
|
|
44
|
+
:type backup_id: str
|
|
45
|
+
:param backup_id: The ID of the backup.
|
|
46
|
+
|
|
47
|
+
:type instance: :class:`~google.cloud.spanner_v1.instance.Instance`
|
|
48
|
+
:param instance: The instance that owns the backup.
|
|
49
|
+
|
|
50
|
+
:type database: str
|
|
51
|
+
:param database: (Optional) The URI of the database that the backup is
|
|
52
|
+
for. Required if the create method needs to be called.
|
|
53
|
+
|
|
54
|
+
:type expire_time: :class:`datetime.datetime`
|
|
55
|
+
:param expire_time: (Optional) The expire time that will be used to
|
|
56
|
+
create the backup. Required if the create method
|
|
57
|
+
needs to be called.
|
|
58
|
+
|
|
59
|
+
:type version_time: :class:`datetime.datetime`
|
|
60
|
+
:param version_time: (Optional) The version time that was specified for
|
|
61
|
+
the externally consistent copy of the database. If
|
|
62
|
+
not present, it is the same as the `create_time` of
|
|
63
|
+
the backup.
|
|
64
|
+
|
|
65
|
+
:type encryption_config:
|
|
66
|
+
:class:`~google.cloud.spanner_admin_database_v1.types.CreateBackupEncryptionConfig`
|
|
67
|
+
or :class:`dict`
|
|
68
|
+
:param encryption_config:
|
|
69
|
+
(Optional) Encryption configuration for the backup.
|
|
70
|
+
If a dict is provided, it must be of the same form as the protobuf
|
|
71
|
+
message :class:`~google.cloud.spanner_admin_database_v1.types.CreateBackupEncryptionConfig`
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __init__(
|
|
75
|
+
self,
|
|
76
|
+
backup_id,
|
|
77
|
+
instance,
|
|
78
|
+
database="",
|
|
79
|
+
expire_time=None,
|
|
80
|
+
version_time=None,
|
|
81
|
+
encryption_config=None,
|
|
82
|
+
source_backup=None,
|
|
83
|
+
):
|
|
84
|
+
self.backup_id = backup_id
|
|
85
|
+
self._instance = instance
|
|
86
|
+
self._database = database
|
|
87
|
+
self._source_backup = source_backup
|
|
88
|
+
self._expire_time = expire_time
|
|
89
|
+
self._create_time = None
|
|
90
|
+
self._version_time = version_time
|
|
91
|
+
self._size_bytes = None
|
|
92
|
+
self._state = None
|
|
93
|
+
self._referencing_databases = None
|
|
94
|
+
self._encryption_info = None
|
|
95
|
+
self._max_expire_time = None
|
|
96
|
+
self._referencing_backups = None
|
|
97
|
+
self._database_dialect = None
|
|
98
|
+
if type(encryption_config) is dict:
|
|
99
|
+
if source_backup:
|
|
100
|
+
self._encryption_config = CopyBackupEncryptionConfig(
|
|
101
|
+
**encryption_config
|
|
102
|
+
)
|
|
103
|
+
else:
|
|
104
|
+
self._encryption_config = CreateBackupEncryptionConfig(
|
|
105
|
+
**encryption_config
|
|
106
|
+
)
|
|
107
|
+
else:
|
|
108
|
+
self._encryption_config = encryption_config
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def name(self):
|
|
112
|
+
"""Backup name used in requests.
|
|
113
|
+
|
|
114
|
+
The backup name is of the form
|
|
115
|
+
|
|
116
|
+
``"projects/../instances/../backups/{backup_id}"``
|
|
117
|
+
|
|
118
|
+
:rtype: str
|
|
119
|
+
:returns: The backup name.
|
|
120
|
+
"""
|
|
121
|
+
return self._instance.name + "/backups/" + self.backup_id
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def database(self):
|
|
125
|
+
"""Database name used in requests.
|
|
126
|
+
|
|
127
|
+
The database name is of the form
|
|
128
|
+
|
|
129
|
+
``"projects/../instances/../backups/{backup_id}"``
|
|
130
|
+
|
|
131
|
+
:rtype: str
|
|
132
|
+
:returns: The database name.
|
|
133
|
+
"""
|
|
134
|
+
return self._database
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def expire_time(self):
|
|
138
|
+
"""Expire time used in creation requests.
|
|
139
|
+
|
|
140
|
+
:rtype: :class:`datetime.datetime`
|
|
141
|
+
:returns: a datetime object representing the expire time of
|
|
142
|
+
this backup
|
|
143
|
+
"""
|
|
144
|
+
return self._expire_time
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def create_time(self):
|
|
148
|
+
"""Create time of this backup.
|
|
149
|
+
|
|
150
|
+
:rtype: :class:`datetime.datetime`
|
|
151
|
+
:returns: a datetime object representing the create time of
|
|
152
|
+
this backup
|
|
153
|
+
"""
|
|
154
|
+
return self._create_time
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def version_time(self):
|
|
158
|
+
"""Version time of this backup.
|
|
159
|
+
|
|
160
|
+
:rtype: :class:`datetime.datetime`
|
|
161
|
+
:returns: a datetime object representing the version time of
|
|
162
|
+
this backup
|
|
163
|
+
"""
|
|
164
|
+
return self._version_time
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def size_bytes(self):
|
|
168
|
+
"""Size of this backup in bytes.
|
|
169
|
+
|
|
170
|
+
:rtype: int
|
|
171
|
+
:returns: the number size of this backup measured in bytes
|
|
172
|
+
"""
|
|
173
|
+
return self._size_bytes
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def state(self):
|
|
177
|
+
"""State of this backup.
|
|
178
|
+
|
|
179
|
+
:rtype: :class:`~google.cloud.spanner_admin_database_v1.types.Backup.State`
|
|
180
|
+
:returns: an enum describing the state of the backup
|
|
181
|
+
"""
|
|
182
|
+
return self._state
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def referencing_databases(self):
|
|
186
|
+
"""List of databases referencing this backup.
|
|
187
|
+
|
|
188
|
+
:rtype: list of strings
|
|
189
|
+
:returns: a list of database path strings which specify the databases still
|
|
190
|
+
referencing this backup
|
|
191
|
+
"""
|
|
192
|
+
return self._referencing_databases
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def encryption_info(self):
|
|
196
|
+
"""Encryption info for this backup.
|
|
197
|
+
:rtype: :class:`~google.cloud.spanner_admin_database_v1.types.EncryptionInfo`
|
|
198
|
+
:returns: a class representing the encryption info
|
|
199
|
+
"""
|
|
200
|
+
return self._encryption_info
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def max_expire_time(self):
|
|
204
|
+
"""The max allowed expiration time of the backup.
|
|
205
|
+
:rtype: :class:`datetime.datetime`
|
|
206
|
+
:returns: a datetime object representing the max expire time of
|
|
207
|
+
this backup
|
|
208
|
+
"""
|
|
209
|
+
return self._max_expire_time
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def referencing_backups(self):
|
|
213
|
+
"""The names of the destination backups being created by copying this source backup.
|
|
214
|
+
:rtype: list of strings
|
|
215
|
+
:returns: a list of backup path strings which specify the backups that are
|
|
216
|
+
referencing this copy backup
|
|
217
|
+
"""
|
|
218
|
+
return self._referencing_backups
|
|
219
|
+
|
|
220
|
+
def database_dialect(self):
|
|
221
|
+
"""Database Dialect for this backup.
|
|
222
|
+
:rtype: :class:`~google.cloud.spanner_admin_database_v1.types.DatabaseDialect`
|
|
223
|
+
:returns: a class representing the dialect of this backup's database
|
|
224
|
+
"""
|
|
225
|
+
return self._database_dialect
|
|
226
|
+
|
|
227
|
+
@classmethod
|
|
228
|
+
def from_pb(cls, backup_pb, instance):
|
|
229
|
+
"""Create an instance of this class from a protobuf message.
|
|
230
|
+
|
|
231
|
+
:type backup_pb: :class:`~google.cloud.spanner_admin_database_v1.types.Backup`
|
|
232
|
+
:param backup_pb: A backup protobuf object.
|
|
233
|
+
|
|
234
|
+
:type instance: :class:`~google.cloud.spanner_v1.instance.Instance`
|
|
235
|
+
:param instance: The instance that owns the backup.
|
|
236
|
+
|
|
237
|
+
:rtype: :class:`Backup`
|
|
238
|
+
:returns: The backup parsed from the protobuf response.
|
|
239
|
+
:raises ValueError:
|
|
240
|
+
if the backup name does not match the expected format or if
|
|
241
|
+
the parsed project ID does not match the project ID on the
|
|
242
|
+
instance's client, or if the parsed instance ID does not match
|
|
243
|
+
the instance's ID.
|
|
244
|
+
"""
|
|
245
|
+
match = _BACKUP_NAME_RE.match(backup_pb.name)
|
|
246
|
+
if match is None:
|
|
247
|
+
raise ValueError(
|
|
248
|
+
"Backup protobuf name was not in the expected format.", backup_pb.name
|
|
249
|
+
)
|
|
250
|
+
if match.group("project") != instance._client.project:
|
|
251
|
+
raise ValueError(
|
|
252
|
+
"Project ID on backup does not match the project ID"
|
|
253
|
+
"on the instance's client"
|
|
254
|
+
)
|
|
255
|
+
instance_id = match.group("instance_id")
|
|
256
|
+
if instance_id != instance.instance_id:
|
|
257
|
+
raise ValueError(
|
|
258
|
+
"Instance ID on database does not match the instance ID"
|
|
259
|
+
"on the instance"
|
|
260
|
+
)
|
|
261
|
+
backup_id = match.group("backup_id")
|
|
262
|
+
return cls(backup_id, instance)
|
|
263
|
+
|
|
264
|
+
def create(self):
|
|
265
|
+
"""Create this backup or backup copy within its instance.
|
|
266
|
+
|
|
267
|
+
:rtype: :class:`~google.api_core.operation.Operation`
|
|
268
|
+
:returns: a future used to poll the status of the create request
|
|
269
|
+
:raises Conflict: if the backup already exists
|
|
270
|
+
:raises NotFound: if the instance owning the backup does not exist
|
|
271
|
+
:raises BadRequest: if the database or expire_time values are invalid
|
|
272
|
+
or expire_time is not set
|
|
273
|
+
"""
|
|
274
|
+
if not self._expire_time:
|
|
275
|
+
raise ValueError("expire_time not set")
|
|
276
|
+
|
|
277
|
+
if not self._database and not self._source_backup:
|
|
278
|
+
raise ValueError("database and source backup both not set")
|
|
279
|
+
|
|
280
|
+
if (
|
|
281
|
+
(
|
|
282
|
+
self._encryption_config
|
|
283
|
+
and self._encryption_config.kms_key_name
|
|
284
|
+
and self._encryption_config.encryption_type
|
|
285
|
+
!= CreateBackupEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION
|
|
286
|
+
)
|
|
287
|
+
and self._encryption_config
|
|
288
|
+
and self._encryption_config.kms_key_name
|
|
289
|
+
and self._encryption_config.encryption_type
|
|
290
|
+
!= CopyBackupEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION
|
|
291
|
+
):
|
|
292
|
+
raise ValueError("kms_key_name only used with CUSTOMER_MANAGED_ENCRYPTION")
|
|
293
|
+
|
|
294
|
+
api = self._instance._client.database_admin_api
|
|
295
|
+
metadata = _metadata_with_prefix(self.name)
|
|
296
|
+
|
|
297
|
+
if self._source_backup:
|
|
298
|
+
request = CopyBackupRequest(
|
|
299
|
+
parent=self._instance.name,
|
|
300
|
+
backup_id=self.backup_id,
|
|
301
|
+
source_backup=self._source_backup,
|
|
302
|
+
expire_time=self._expire_time,
|
|
303
|
+
encryption_config=self._encryption_config,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
future = api.copy_backup(
|
|
307
|
+
request=request,
|
|
308
|
+
metadata=metadata,
|
|
309
|
+
)
|
|
310
|
+
return future
|
|
311
|
+
|
|
312
|
+
backup = BackupPB(
|
|
313
|
+
database=self._database,
|
|
314
|
+
expire_time=self.expire_time,
|
|
315
|
+
version_time=self.version_time,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
request = CreateBackupRequest(
|
|
319
|
+
parent=self._instance.name,
|
|
320
|
+
backup_id=self.backup_id,
|
|
321
|
+
backup=backup,
|
|
322
|
+
encryption_config=self._encryption_config,
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
future = api.create_backup(
|
|
326
|
+
request=request,
|
|
327
|
+
metadata=metadata,
|
|
328
|
+
)
|
|
329
|
+
return future
|
|
330
|
+
|
|
331
|
+
def exists(self):
|
|
332
|
+
"""Test whether this backup exists.
|
|
333
|
+
|
|
334
|
+
:rtype: bool
|
|
335
|
+
:returns: True if the backup exists, else False.
|
|
336
|
+
"""
|
|
337
|
+
api = self._instance._client.database_admin_api
|
|
338
|
+
metadata = _metadata_with_prefix(self.name)
|
|
339
|
+
|
|
340
|
+
try:
|
|
341
|
+
api.get_backup(name=self.name, metadata=metadata)
|
|
342
|
+
except NotFound:
|
|
343
|
+
return False
|
|
344
|
+
return True
|
|
345
|
+
|
|
346
|
+
def reload(self):
|
|
347
|
+
"""Reload this backup.
|
|
348
|
+
|
|
349
|
+
Refresh the stored backup properties.
|
|
350
|
+
|
|
351
|
+
:raises NotFound: if the backup does not exist
|
|
352
|
+
"""
|
|
353
|
+
api = self._instance._client.database_admin_api
|
|
354
|
+
metadata = _metadata_with_prefix(self.name)
|
|
355
|
+
pb = api.get_backup(name=self.name, metadata=metadata)
|
|
356
|
+
self._database = pb.database
|
|
357
|
+
self._expire_time = pb.expire_time
|
|
358
|
+
self._create_time = pb.create_time
|
|
359
|
+
self._version_time = pb.version_time
|
|
360
|
+
self._size_bytes = pb.size_bytes
|
|
361
|
+
self._state = BackupPB.State(pb.state)
|
|
362
|
+
self._referencing_databases = pb.referencing_databases
|
|
363
|
+
self._encryption_info = pb.encryption_info
|
|
364
|
+
self._max_expire_time = pb.max_expire_time
|
|
365
|
+
self._referencing_backups = pb.referencing_backups
|
|
366
|
+
|
|
367
|
+
def update_expire_time(self, new_expire_time):
|
|
368
|
+
"""Update the expire time of this backup.
|
|
369
|
+
|
|
370
|
+
:type new_expire_time: :class:`datetime.datetime`
|
|
371
|
+
:param new_expire_time: the new expire time timestamp
|
|
372
|
+
"""
|
|
373
|
+
api = self._instance._client.database_admin_api
|
|
374
|
+
metadata = _metadata_with_prefix(self.name)
|
|
375
|
+
backup_update = BackupPB(
|
|
376
|
+
name=self.name,
|
|
377
|
+
expire_time=new_expire_time,
|
|
378
|
+
)
|
|
379
|
+
update_mask = {"paths": ["expire_time"]}
|
|
380
|
+
api.update_backup(
|
|
381
|
+
backup=backup_update, update_mask=update_mask, metadata=metadata
|
|
382
|
+
)
|
|
383
|
+
self._expire_time = new_expire_time
|
|
384
|
+
|
|
385
|
+
def is_ready(self):
|
|
386
|
+
"""Test whether this backup is ready for use.
|
|
387
|
+
|
|
388
|
+
:rtype: bool
|
|
389
|
+
:returns: True if the backup state is READY, else False.
|
|
390
|
+
"""
|
|
391
|
+
return self.state == BackupPB.State.READY
|
|
392
|
+
|
|
393
|
+
def delete(self):
|
|
394
|
+
"""Delete this backup."""
|
|
395
|
+
api = self._instance._client.database_admin_api
|
|
396
|
+
metadata = _metadata_with_prefix(self.name)
|
|
397
|
+
api.delete_backup(name=self.name, metadata=metadata)
|