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"""Shared resource flags for Cloud IoT commands."""
17
18from __future__ import absolute_import
19from __future__ import division
20from __future__ import unicode_literals
21
22from googlecloudsdk.calliope.concepts import concepts
23from googlecloudsdk.command_lib.util.concepts import concept_parsers
24from googlecloudsdk.command_lib.util.concepts import presentation_specs
25
26
27def DeviceAttributeConfig(name='device'):
28  return concepts.ResourceParameterAttributeConfig(
29      name=name,
30      help_text='The device of the {resource}.',
31      completion_request_params={'fieldMask': 'name'},
32      completion_id_field='id')
33
34
35def RegistryAttributeConfig():
36  return concepts.ResourceParameterAttributeConfig(
37      name='registry',
38      help_text='The device registry for the {resource}.')
39
40
41def RegionAttributeConfig():
42  return concepts.ResourceParameterAttributeConfig(
43      name='region',
44      help_text='The Cloud region for the {resource}.')
45
46
47def GetDeviceResourceSpec(resource_name='device'):
48  return concepts.ResourceSpec(
49      'cloudiot.projects.locations.registries.devices',
50      resource_name=resource_name,
51      devicesId=DeviceAttributeConfig(name=resource_name),
52      registriesId=RegistryAttributeConfig(),
53      locationsId=RegionAttributeConfig(),
54      projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
55      disable_auto_completers=False)
56
57
58def GetRegistryResourceSpec():
59  return concepts.ResourceSpec(
60      'cloudiot.projects.locations.registries',
61      resource_name='registry',
62      registriesId=RegistryAttributeConfig(),
63      locationsId=RegionAttributeConfig(),
64      projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
65      disable_auto_completers=False)
66
67
68def GetRegionResourceSpec():
69  return concepts.ResourceSpec(
70      'cloudiot.projects.locations',
71      resource_name='region',
72      locationsId=RegionAttributeConfig(),
73      projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG)
74
75
76def AddDeviceResourceArg(parser, verb, positional=True):
77  """Add a resource argument for a cloud IOT device.
78
79  NOTE: Must be used only if it's the only resource arg in the command.
80
81  Args:
82    parser: the parser for the command.
83    verb: str, the verb to describe the resource, such as 'to update'.
84    positional: bool, if True, means that the device ID is a positional rather
85      than a flag.
86  """
87  if positional:
88    name = 'device'
89  else:
90    name = '--device'
91  concept_parsers.ConceptParser.ForResource(
92      name,
93      GetDeviceResourceSpec(),
94      'The device {}.'.format(verb),
95      required=True).AddToParser(parser)
96
97
98def AddRegistryResourceArg(parser, verb, positional=True):
99  """Add a resource argument for a cloud IOT device registry.
100
101  NOTE: Must be used only if it's the only resource arg in the command.
102
103  Args:
104    parser: the parser for the command.
105    verb: str, the verb to describe the resource, such as 'to update'.
106    positional: bool, if True, means that the device ID is a positional rather
107      than a flag.
108  """
109  if positional:
110    name = 'registry'
111  else:
112    name = '--registry'
113  concept_parsers.ConceptParser.ForResource(
114      name,
115      GetRegistryResourceSpec(),
116      'The device registry {}.'.format(verb),
117      required=True).AddToParser(parser)
118
119
120def AddRegionResourceArg(parser, verb):
121  """Add a resource argument for a cloud IOT region.
122
123  NOTE: Must be used only if it's the only resource arg in the command.
124
125  Args:
126    parser: the parser for the command.
127    verb: str, the verb to describe the resource, such as 'to update'.
128  """
129  concept_parsers.ConceptParser.ForResource(
130      '--region',
131      GetRegionResourceSpec(),
132      'The Cloud region {}.'.format(verb),
133      required=True).AddToParser(parser)
134
135
136def CreateDevicePresentationSpec(verb, help_text='The device {}.',
137                                 name='device', required=False,
138                                 prefixes=True, positional=False):
139  """Build ResourcePresentationSpec for generic device Resource.
140
141  NOTE: Should be used when there are multiple resources args in the command.
142
143  Args:
144    verb: string, the verb to describe the resource, such as 'to bind'.
145    help_text: string, the help text for the entire resource arg group. Should
146      have a format specifier (`{}`) to insert verb.
147    name: string, name of resource anchor argument.
148    required: bool, whether or not this resource arg is required.
149    prefixes: bool, if True the resource name will be used as a prefix for
150      the flags in the resource group.
151    positional: bool, if True, means that the device ID is a positional rather
152      than a flag.
153  Returns:
154    ResourcePresentationSpec, presentation spec for device.
155  """
156  arg_name = name if positional else '--' + name
157  arg_help = help_text.format(verb)
158
159  return presentation_specs.ResourcePresentationSpec(
160      arg_name,
161      GetDeviceResourceSpec(name),
162      arg_help,
163      required=required,
164      prefixes=prefixes
165  )
166
167
168def _GetBindResourceConcepts(verb='to bind to'):
169  """Build ConceptParser for (un)bind commands resource args."""
170  arg_specs = [
171      CreateDevicePresentationSpec(  # gateway spec
172          verb,
173          help_text='The gateway device {}.',
174          name='gateway',
175          required=True),
176      CreateDevicePresentationSpec(  # device spec
177          verb,
178          help_text='The device {} the gateway.',
179          required=True),
180  ]
181
182  fallthroughs = {
183      '--device.registry': ['--gateway.registry'],
184      '--gateway.registry': ['--device.registry']
185  }
186
187  return concept_parsers.ConceptParser(arg_specs, fallthroughs)
188
189
190def AddBindResourceArgsToParser(parser):
191  """Add resource args for gateways (un)bind commands to parser."""
192  _GetBindResourceConcepts().AddToParser(parser)
193
194
195def BindAdditionalArgsHook():
196  return [_GetBindResourceConcepts()]
197
198
199def UnBindAdditionalArgsHook():
200  return [_GetBindResourceConcepts('to unbind from')]
201
202