1# -*- coding: utf-8 -*- #
2# Copyright 2017 Google LLC. All Rights Reserved.
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#    http://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"""Helpers for compute instance-groups managed instance-configs commands."""
17
18from __future__ import absolute_import
19from __future__ import division
20from __future__ import unicode_literals
21
22from googlecloudsdk.api_lib.compute import managed_instance_groups_utils
23from googlecloudsdk.api_lib.compute import path_simplifier
24import six
25
26
27class InstanceConfigsGetterWithSimpleCache(object):
28  """Class for getting existence of instance configs (with simple cache).
29
30  Class caches one previously gotten per instance config. May be used if during
31  the same workflow there is need to get (or verify existence) the same per
32  instance config multiple times.
33  """
34
35  def __init__(self, client):
36    self._client = client
37    self._cached_per_instance_config = None
38    self._key_of_cached_per_instance_config = None
39
40  def get_instance_config(self, igm_ref, instance_ref):
41    """Returns instance config for given reference (uses simple cache)."""
42    per_instance_config_key = self._build_key(
43        igm_ref=igm_ref, instance_ref=instance_ref)
44    if self._key_of_cached_per_instance_config != per_instance_config_key:
45      self._cached_per_instance_config = self._do_get_instance_config(
46          igm_ref=igm_ref, instance_ref=instance_ref)
47      self._key_of_cached_per_instance_config = per_instance_config_key
48    return self._cached_per_instance_config
49
50  def check_if_instance_config_exists(self,
51                                      igm_ref,
52                                      instance_ref,
53                                      should_exist=True):
54    """Checks if instance config exists for given instance reference."""
55    per_instance_config = self.get_instance_config(
56        igm_ref=igm_ref, instance_ref=instance_ref)
57    if should_exist:
58      if per_instance_config is None:
59        raise managed_instance_groups_utils.ResourceNotFoundException(
60            'Instance config for {instance} does not exist'.format(
61                instance=instance_ref))
62    else:
63      if per_instance_config is not None:
64        raise managed_instance_groups_utils.ResourceAlreadyExistsException(
65            'Instance config for {instance} already exists'.format(
66                instance=instance_ref))
67
68  @staticmethod
69  def _build_key(igm_ref, instance_ref):
70    """Builds simple key object for combination of IGM and instance refs."""
71    return (igm_ref, instance_ref)
72
73  def _do_get_instance_config(self, igm_ref, instance_ref):
74    """Returns instance config for given instance."""
75    instance_name = path_simplifier.Name(six.text_type(instance_ref))
76    filter_param = 'name eq {0}'.format(instance_name)
77    if igm_ref.Collection() == 'compute.instanceGroupManagers':
78      service = self._client.apitools_client.instanceGroupManagers
79      request = (self._client.messages.
80                 ComputeInstanceGroupManagersListPerInstanceConfigsRequest)(
81                     instanceGroupManager=igm_ref.Name(),
82                     project=igm_ref.project,
83                     zone=igm_ref.zone,
84                     filter=filter_param,
85                     maxResults=1,
86                 )
87    elif igm_ref.Collection() == 'compute.regionInstanceGroupManagers':
88      service = self._client.apitools_client.regionInstanceGroupManagers
89      request = (
90          self._client.messages.
91          ComputeRegionInstanceGroupManagersListPerInstanceConfigsRequest)(
92              instanceGroupManager=igm_ref.Name(),
93              project=igm_ref.project,
94              region=igm_ref.region,
95              filter=filter_param,
96              maxResults=1,
97          )
98    else:
99      raise ValueError('Unknown reference type {0}'.format(
100          igm_ref.Collection()))
101    per_instance_configs = service.ListPerInstanceConfigs(request).items
102    if per_instance_configs:
103      return per_instance_configs[0]
104    else:
105      return None
106