gcpdiag.queries.looker

Queries related to GCP Looker Core.
class Instance(gcpdiag.models.Resource):
26class Instance(models.Resource):
27  """Represents a Looker Core Instance."""
28  _resource_data: dict
29
30  def __init__(self, project_id, resource_data):
31    super().__init__(project_id=project_id)
32    self._resource_data = resource_data
33
34  @property
35  def name(self) -> str:
36    return self._resource_data['name']
37
38  @property
39  def full_path(self) -> str:
40    return self._resource_data['name']
41
42  @property
43  def short_path(self) -> str:
44    return '/'.join(self.full_path.split('/')[-4:])
45
46  @property
47  def status(self) -> str:
48    return self._resource_data.get('state', 'STATE_UNSPECIFIED')
49
50  @property
51  def create_time(self) -> str:
52    return self._resource_data.get('createTime', '')
53
54  @property
55  def update_time(self) -> str:
56    return self._resource_data.get('updateTime', '')
57
58  @property
59  def platform_edition(self) -> str:
60    return self._resource_data.get('platformEdition', '')
61
62  @property
63  def looker_version(self) -> str:
64    return self._resource_data.get('lookerVersion', '')
65
66  @property
67  def looker_uri(self) -> str:
68    return self._resource_data.get('lookerUri', '')

Represents a Looker Core Instance.

Instance(project_id, resource_data)
30  def __init__(self, project_id, resource_data):
31    super().__init__(project_id=project_id)
32    self._resource_data = resource_data
name: str
34  @property
35  def name(self) -> str:
36    return self._resource_data['name']
full_path: str
38  @property
39  def full_path(self) -> str:
40    return self._resource_data['name']

Returns the full path of this resource.

Example: 'projects/gcpdiag-gke-1-9b90/zones/europe-west4-a/clusters/gke1'

short_path: str
42  @property
43  def short_path(self) -> str:
44    return '/'.join(self.full_path.split('/')[-4:])

Returns the short name for this resource.

Note that it isn't clear from this name what kind of resource it is.

Example: 'gke1'

status: str
46  @property
47  def status(self) -> str:
48    return self._resource_data.get('state', 'STATE_UNSPECIFIED')
create_time: str
50  @property
51  def create_time(self) -> str:
52    return self._resource_data.get('createTime', '')
update_time: str
54  @property
55  def update_time(self) -> str:
56    return self._resource_data.get('updateTime', '')
platform_edition: str
58  @property
59  def platform_edition(self) -> str:
60    return self._resource_data.get('platformEdition', '')
looker_version: str
62  @property
63  def looker_version(self) -> str:
64    return self._resource_data.get('lookerVersion', '')
looker_uri: str
66  @property
67  def looker_uri(self) -> str:
68    return self._resource_data.get('lookerUri', '')
class Operation(gcpdiag.models.Resource):
 71class Operation(models.Resource):
 72  """Represents Looker Core long-running operation."""
 73
 74  def __init__(self, project_id, resource_data):
 75    super().__init__(project_id=project_id)
 76    self._resource_data = resource_data
 77
 78  @property
 79  def full_path(self) -> str:
 80    return self._resource_data.get('name', '')
 81
 82  @property
 83  def name(self) -> str:
 84    return self._resource_data['name'].split('/')[-1]
 85
 86  @property
 87  def metadata(self) -> dict:
 88    return self._resource_data.get('metadata', {})
 89
 90  @property
 91  def done(self) -> bool:
 92    return self._resource_data.get('done', False)
 93
 94  @property
 95  def target(self) -> str:
 96    return self._resource_data.get('metadata', {}).get('target', '')
 97
 98  @property
 99  def verb(self) -> str:
100    return self._resource_data.get('metadata', {}).get('verb', '')
101
102  @property
103  def status(self) -> str:
104    return 'Completed' if self._resource_data.get('done') else 'In Progress'
105
106  @property
107  def location_id(self) -> str:
108    parts = self._resource_data.get('name', '').split('/')
109    return parts[3] if len(parts) > 3 else ''
110
111  @property
112  def instance_name(self) -> str:
113    parts = self.target.split('/')
114    return parts[5] if len(parts) >= 6 else ''
115
116  @property
117  def operation_type(self) -> str:
118    return self.verb
119
120  @property
121  def action(self) -> str:
122    if self.verb == 'update' and not self.done:
123      return 'Updating Instance'
124    else:
125      parts = self.target.split('/')
126      return parts[6] if len(parts) >= 7 else ''
127
128  @property
129  def create_time(self) -> datetime:
130    create_time_str = self._resource_data.get('metadata',
131                                              {}).get('createTime', '')
132    if create_time_str:
133      return datetime.fromisoformat(
134          create_time_str.rstrip('Z')).replace(tzinfo=timezone.utc)
135    return datetime.now(timezone.utc)

Represents Looker Core long-running operation.

Operation(project_id, resource_data)
74  def __init__(self, project_id, resource_data):
75    super().__init__(project_id=project_id)
76    self._resource_data = resource_data
full_path: str
78  @property
79  def full_path(self) -> str:
80    return self._resource_data.get('name', '')

Returns the full path of this resource.

Example: 'projects/gcpdiag-gke-1-9b90/zones/europe-west4-a/clusters/gke1'

name: str
82  @property
83  def name(self) -> str:
84    return self._resource_data['name'].split('/')[-1]
metadata: dict
86  @property
87  def metadata(self) -> dict:
88    return self._resource_data.get('metadata', {})
done: bool
90  @property
91  def done(self) -> bool:
92    return self._resource_data.get('done', False)
target: str
94  @property
95  def target(self) -> str:
96    return self._resource_data.get('metadata', {}).get('target', '')
verb: str
 98  @property
 99  def verb(self) -> str:
100    return self._resource_data.get('metadata', {}).get('verb', '')
status: str
102  @property
103  def status(self) -> str:
104    return 'Completed' if self._resource_data.get('done') else 'In Progress'
location_id: str
106  @property
107  def location_id(self) -> str:
108    parts = self._resource_data.get('name', '').split('/')
109    return parts[3] if len(parts) > 3 else ''
instance_name: str
111  @property
112  def instance_name(self) -> str:
113    parts = self.target.split('/')
114    return parts[5] if len(parts) >= 6 else ''
operation_type: str
116  @property
117  def operation_type(self) -> str:
118    return self.verb
action: str
120  @property
121  def action(self) -> str:
122    if self.verb == 'update' and not self.done:
123      return 'Updating Instance'
124    else:
125      parts = self.target.split('/')
126      return parts[6] if len(parts) >= 7 else ''
create_time: datetime.datetime
128  @property
129  def create_time(self) -> datetime:
130    create_time_str = self._resource_data.get('metadata',
131                                              {}).get('createTime', '')
132    if create_time_str:
133      return datetime.fromisoformat(
134          create_time_str.rstrip('Z')).replace(tzinfo=timezone.utc)
135    return datetime.now(timezone.utc)
@caching.cached_api_call
def get_instances( context: gcpdiag.models.Context) -> Dict[str, Instance]:
156@caching.cached_api_call
157def get_instances(context: models.Context) -> Dict[str, Instance]:
158  """Get a list of Instances from the given GCP project."""
159  instances: Dict[str, Instance] = {}
160  if not apis.is_enabled(context.project_id, 'looker'):
161    return instances
162  looker_api = apis.get_api('looker', 'v1', context.project_id)
163
164  try:
165    locations_to_scan = _get_locations_to_scan(context, looker_api)
166  except utils.GcpApiError as err:
167    raise err
168
169  for loc_id in locations_to_scan:
170    try:
171      parent_path = f'projects/{context.project_id}/locations/{loc_id}'
172      request = looker_api.projects().locations().instances().list(
173          parent=parent_path)
174      for inst in apis_utils.list_all(
175          request=request,
176          next_function=looker_api.projects().locations().instances().list_next,
177          response_keyword='instances'):
178        if not context.match_project_resource(resource=inst.get('name', '')):
179          continue
180        instance = Instance(project_id=context.project_id, resource_data=inst)
181        instances[instance.name] = instance
182    except googleapiclient.errors.HttpError as err:
183      logging.warning('Could not list instances for location %s: %s', loc_id,
184                      err)
185      continue
186  return instances

Get a list of Instances from the given GCP project.

@caching.cached_api_call
def get_operations( context: gcpdiag.models.Context) -> MutableMapping[str, MutableMapping[str, List[Operation]]]:
189@caching.cached_api_call
190def get_operations(
191    context: models.Context
192) -> MutableMapping[str, MutableMapping[str, List[Operation]]]:
193  """Get a list of recent operations from the given GCP project."""
194  location_instance_operations: MutableMapping[str, MutableMapping[
195      str, List[Operation]]] = {}
196  if not apis.is_enabled(context.project_id, 'looker'):
197    return location_instance_operations
198
199  looker_api = apis.get_api('looker', 'v1', context.project_id)
200
201  now = context.parameters.get('now', datetime.now(timezone.utc))
202  one_day_ago = now - timedelta(days=1)
203
204  try:
205    locations_to_scan = _get_locations_to_scan(context, looker_api)
206  except utils.GcpApiError:
207    return {}
208
209  for location_id in locations_to_scan:
210    try:
211      op_request_name = f'projects/{context.project_id}/locations/{location_id}'
212      operations_request = looker_api.projects().locations().operations().list(
213          name=op_request_name)
214      for resp_op in apis_utils.list_all(request=operations_request,
215                                         next_function=looker_api.projects().
216                                         locations().operations().list_next,
217                                         response_keyword='operations'):
218        operation_details = looker_api.projects().locations().operations().get(
219            name=resp_op['name']).execute(num_retries=config.API_RETRIES)
220        operation = Operation(project_id=context.project_id,
221                              resource_data=operation_details)
222
223        if operation.create_time >= one_day_ago:
224          location_instance_operations.setdefault(operation.location_id,
225                                                  {}).setdefault(
226                                                      operation.instance_name,
227                                                      []).append(operation)
228    except googleapiclient.errors.HttpError as err:
229      logging.warning('Could not list operations for location %s: %s',
230                      location_id, err)
231      continue
232
233  return location_instance_operations

Get a list of recent operations from the given GCP project.