1# Copyright 2016 Google LLC
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"""Define Cloud Logging API Sinks."""
16
17from google.cloud.exceptions import NotFound
18
19
20class Sink(object):
21 """Sinks represent filtered exports for log entries.
22
23 See https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks
24 """
25
26 def __init__(
27 self, name, *, filter_=None, parent=None, destination=None, client=None
28 ):
29 """
30 Args:
31 name (str): The name of the sink.
32 parent(Optional[str]): The resource in which to create the sink:
33
34 ::
35
36 "projects/[PROJECT_ID]"
37 "organizations/[ORGANIZATION_ID]"
38 "billingAccounts/[BILLING_ACCOUNT_ID]"
39 "folders/[FOLDER_ID]".
40
41 Defaults to the project stored on the client.
42 filter_ (Optional[str]): The advanced logs filter expression defining
43 the entries exported by the sink.
44 destination (Optional[str]): Destination URI for the entries exported by the sink.
45 If not passed, the instance should already exist, to
46 be refreshed via :meth:`reload`.
47 client (Optional[~logging_v2.client.Client]): A client which holds
48 credentials and project configuration for the sink (which requires a project).
49 """
50 self.name = name
51 self.filter_ = filter_
52 self.destination = destination
53 self._client = client
54 self._parent = parent
55 self._writer_identity = None
56
57 @property
58 def client(self):
59 """Client bound to the sink."""
60 return self._client
61
62 @property
63 def parent(self):
64 """Parent resource of the sink (project, organization, billingAccount, or folder)."""
65 if self._parent is None:
66 self._parent = f"projects/{self.client.project}"
67 return self._parent
68
69 @property
70 def full_name(self):
71 """Fully-qualified name used in sink APIs"""
72 return f"{self.parent}/sinks/{self.name}"
73
74 @property
75 def path(self):
76 """URL path for the sink's APIs"""
77 return f"/{self.full_name}"
78
79 @property
80 def writer_identity(self):
81 """Identity used for exports via the sink"""
82 return self._writer_identity
83
84 def _update_from_api_repr(self, resource):
85 """Helper for API methods returning sink resources."""
86 self.destination = resource["destination"]
87 self.filter_ = resource.get("filter")
88 self._writer_identity = resource.get("writerIdentity")
89
90 @classmethod
91 def from_api_repr(cls, resource, client, *, parent=None):
92 """Construct a sink given its API representation
93
94 Args:
95 resource (dict): sink resource representation returned from the API
96 client (~logging_v2.client.Client): Client which holds
97 credentials and project configuration for the sink.
98 parent(Optional[str]): The resource in which to create the sink:
99
100 ::
101
102 "projects/[PROJECT_ID]"
103 "organizations/[ORGANIZATION_ID]"
104 "billingAccounts/[BILLING_ACCOUNT_ID]"
105 "folders/[FOLDER_ID]".
106
107 Defaults to the project stored on the client.
108
109 Returns:
110 ~logging_v2.sink.Sink: Sink parsed from ``resource``.
111
112 Raises:
113 ValueError: if ``client`` is not ``None`` and the
114 project from the resource does not agree with the project
115 from the client.
116 """
117 sink_name = resource["name"]
118 instance = cls(sink_name, client=client, parent=parent)
119 instance._update_from_api_repr(resource)
120 return instance
121
122 def _require_client(self, client):
123 """Check client or verify over-ride. Also sets ``parent``.
124
125 Args:
126 client (Union[None, ~logging_v2.client.Client]):
127 The client to use. If not passed, falls back to the
128 ``client`` stored on the current sink.
129
130 Returns:
131 ~logging_v2.client.Client: The client passed in
132 or the currently bound client.
133 """
134 if client is None:
135 client = self._client
136 return client
137
138 def create(self, *, client=None, unique_writer_identity=False):
139 """Create the sink via a PUT request
140
141 See
142 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/create
143
144 Args:
145 client (Optional[~logging_v2.client.Client]):
146 The client to use. If not passed, falls back to the
147 ``client`` stored on the current sink.
148 unique_writer_identity (Optional[bool]): Determines the kind of
149 IAM identity returned as writer_identity in the new sink.
150 """
151 client = self._require_client(client)
152 resource = client.sinks_api.sink_create(
153 self.parent,
154 self.name,
155 self.filter_,
156 self.destination,
157 unique_writer_identity=unique_writer_identity,
158 )
159 self._update_from_api_repr(resource)
160
161 def exists(self, *, client=None):
162 """Test for the existence of the sink via a GET request
163
164 See
165 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/get
166
167 Args:
168 client (Optional[~logging_v2.client.Client]):
169 The client to use. If not passed, falls back to the
170 ``client`` stored on the current sink.
171
172 Returns:
173 bool: Boolean indicating existence of the sink.
174 """
175 client = self._require_client(client)
176
177 try:
178 client.sinks_api.sink_get(self.full_name)
179 except NotFound:
180 return False
181 else:
182 return True
183
184 def reload(self, *, client=None):
185 """Sync local sink configuration via a GET request
186
187 See
188 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/get
189
190 Args:
191 client (Optional[~logging_v2.client.Client]):
192 The client to use. If not passed, falls back to the
193 ``client`` stored on the current sink.
194 """
195 client = self._require_client(client)
196 resource = client.sinks_api.sink_get(self.full_name)
197 self._update_from_api_repr(resource)
198
199 def update(self, *, client=None, unique_writer_identity=False):
200 """Update sink configuration via a PUT request
201
202 See
203 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/update
204
205 Args:
206 client (Optional[~logging_v2.client.Client]):
207 The client to use. If not passed, falls back to the
208 ``client`` stored on the current sink.
209 unique_writer_identity (Optional[bool]): Determines the kind of
210 IAM identity returned as writer_identity in the new sink.
211 """
212 client = self._require_client(client)
213 resource = client.sinks_api.sink_update(
214 self.full_name,
215 self.filter_,
216 self.destination,
217 unique_writer_identity=unique_writer_identity,
218 )
219 self._update_from_api_repr(resource)
220
221 def delete(self, *, client=None):
222 """Delete a sink via a DELETE request
223
224 See
225 https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/delete
226
227 Args:
228 client (Optional[~logging_v2.client.Client]):
229 The client to use. If not passed, falls back to the
230 ``client`` stored on the current sink.
231 """
232 client = self._require_client(client)
233 client.sinks_api.sink_delete(self.full_name)