1# -*- coding: utf-8 -*- #
2# Copyright 2020 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"""API client library for Cloud Domains Registrations."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import unicode_literals
20
21from apitools.base.py import list_pager
22from googlecloudsdk.api_lib.util import apis
23from googlecloudsdk.calliope import base
24from googlecloudsdk.core import exceptions
25
26ALPHA_API_VERSION = 'v1alpha2'
27BETA_API_VERSION = 'v1beta1'
28
29
30def GetApiVersionFromArgs(args):
31  """Return API version based on args."""
32  release_track = args.calliope_command.ReleaseTrack()
33  if release_track == base.ReleaseTrack.ALPHA:
34    return ALPHA_API_VERSION
35  if release_track == base.ReleaseTrack.BETA:
36    return BETA_API_VERSION
37  raise exceptions.UnsupportedReleaseTrackError(release_track)
38
39
40def GetClientInstance(api_version):
41  return apis.GetClientInstance('domains', api_version)
42
43
44def GetMessagesModule(api_version, client=None):
45  client = client or GetClientInstance(api_version)
46  return client.MESSAGES_MODULE
47
48
49class RegistrationsClient(object):
50  """Client for registrations service in the Cloud Domains API."""
51
52  def __init__(self, api_version, client=None, messages=None):
53    self.client = client or GetClientInstance(api_version)
54    self.messages = messages or GetMessagesModule(api_version, client)
55    self._service = self.client.projects_locations_registrations
56
57  def Register(self,
58               parent_ref,
59               domain,
60               dns_settings,
61               contact_settings,
62               yearly_price,
63               labels=None,
64               hsts_notice_accepted=False,
65               public_privacy_accepted=False,
66               validate_only=False):
67    """Creates a Registration.
68
69    Args:
70      parent_ref: a Resource reference to a domains.projects.locations resource
71        for the parent of this registration.
72      domain: str, the name of the domain to register. Used as resource name.
73      dns_settings: DnsSettings to be used.
74      contact_settings: ContactSettings to be used.
75      yearly_price: price for the domain registration and its cost for the
76        following years.
77      labels: Unified GCP Labels for the resource.
78      hsts_notice_accepted: bool, Whether HSTS notice was presented & accepted.
79      public_privacy_accepted: bool, Whether public privacy notice was presented
80        & accepted.
81      validate_only: If set to true, performs only validation, without creating.
82
83    Returns:
84      Operation: the long running operation to regsiter a domain.
85    """
86    domain_notices = []
87    if hsts_notice_accepted:
88      domain_notices = [
89          self.messages.RegisterDomainRequest
90          .DomainNoticesValueListEntryValuesEnum.HSTS_PRELOADED
91      ]
92    contact_notices = []
93    if public_privacy_accepted:
94      contact_notices = [
95          self.messages.RegisterDomainRequest
96          .ContactNoticesValueListEntryValuesEnum
97          .PUBLIC_CONTACT_DATA_ACKNOWLEDGEMENT
98      ]
99    req = self.messages.DomainsProjectsLocationsRegistrationsRegisterRequest(
100        parent=parent_ref.RelativeName(),
101        registerDomainRequest=self.messages.RegisterDomainRequest(
102            registration=self.messages.Registration(
103                domainName=domain,
104                dnsSettings=dns_settings,
105                contactSettings=contact_settings,
106                labels=labels),
107            domainNotices=domain_notices,
108            contactNotices=contact_notices,
109            yearlyPrice=yearly_price,
110            validateOnly=validate_only))
111
112    return self._service.Register(req)
113
114  def Export(self, registration_ref):
115    req = self.messages.DomainsProjectsLocationsRegistrationsExportRequest(
116        name=registration_ref.RelativeName())
117    return self._service.Export(req)
118
119  def Delete(self, registration_ref):
120    req = self.messages.DomainsProjectsLocationsRegistrationsDeleteRequest(
121        name=registration_ref.RelativeName())
122    return self._service.Delete(req)
123
124  def Get(self, registration_ref):
125    get_req = self.messages.DomainsProjectsLocationsRegistrationsGetRequest(
126        name=registration_ref.RelativeName())
127    return self._service.Get(get_req)
128
129  def RetrieveAuthorizationCode(self, registration_ref):
130    # pylint: disable=line-too-long
131    req = self.messages.DomainsProjectsLocationsRegistrationsRetrieveAuthorizationCodeRequest(
132        registration=registration_ref.RelativeName())
133    return self._service.RetrieveAuthorizationCode(req)
134
135  def ResetAuthorizationCode(self, registration_ref):
136    # pylint: disable=line-too-long
137    req = self.messages.DomainsProjectsLocationsRegistrationsResetAuthorizationCodeRequest(
138        registration=registration_ref.RelativeName())
139    return self._service.ResetAuthorizationCode(req)
140
141  def List(self, parent_ref, limit=None, page_size=None, list_filter=None):
142    """List the domain registrations in a given project.
143
144    Args:
145      parent_ref: a Resource reference to a domains.projects.locations resource
146        to list registrations for.
147      limit: int, the total number of results to return from the API.
148      page_size: int, the number of results in each batch from the API.
149      list_filter: str, filter to apply in the list request.
150
151    Returns:
152      A generator of the domain registrations in the project.
153    """
154    list_req = self.messages.DomainsProjectsLocationsRegistrationsListRequest(
155        parent=parent_ref.RelativeName(), filter=list_filter)
156    return list_pager.YieldFromList(
157        self._service,
158        list_req,
159        batch_size=page_size,
160        limit=limit,
161        field='registrations',
162        batch_size_attribute='pageSize')
163
164  def Patch(self, registration_ref, labels=None):
165    """Updates a Registration.
166
167    Used for updating labels.
168
169    Args:
170      registration_ref: a Resource reference to a
171        domains.projects.locations.registrations resource.
172      labels: Unified GCP Labels for the resource.
173
174    Returns:
175      Operation: the long running operation to patch registration.
176    """
177    registration = self.messages.Registration()
178    registration.labels = labels
179    update_mask = 'labels'
180
181    patch_req = self.messages.DomainsProjectsLocationsRegistrationsPatchRequest(
182        registration=registration,
183        name=registration_ref.RelativeName(),
184        updateMask=update_mask)
185
186    return self._service.Patch(patch_req)
187
188  def ConfigureManagement(self, registration_ref, transfer_lock):
189    """Updates management settings.
190
191    Args:
192      registration_ref: a Resource reference to a
193        domains.projects.locations.registrations resource.
194      transfer_lock: The transfer lock state.
195
196    Returns:
197      Operation: the long running operation to configure management
198        registration.
199    """
200    management_settings = self.messages.ManagementSettings(
201        transferLockState=transfer_lock)
202
203    # pylint: disable=line-too-long
204    req = self.messages.DomainsProjectsLocationsRegistrationsConfigureManagementSettingsRequest(
205        registration=registration_ref.RelativeName(),
206        configureManagementSettingsRequest=self.messages
207        .ConfigureManagementSettingsRequest(
208            managementSettings=management_settings,
209            updateMask='transfer_lock_state'))
210
211    return self._service.ConfigureManagementSettings(req)
212
213  def ConfigureDNS(self, registration_ref, dns_settings, updated,
214                   validate_only):
215    """Calls ConfigureDNSSettings method.
216
217    Args:
218      registration_ref: Registration resource reference.
219      dns_settings: New DNS Settings.
220      updated: dns_util.DnsUpdateMask object representing an update mask.
221      validate_only: validate_only flag.
222
223    Returns:
224      Long Running Operation reference.
225    """
226
227    updated_list = []
228    if updated.glue_records:
229      updated_list += ['glue_records']
230    if updated.google_domains_dnssec:
231      if updated.name_servers:
232        updated_list += ['google_domains_dns']
233      else:
234        updated_list += ['google_domains_dns.ds_state']
235    if updated.custom_dnssec:
236      if updated.name_servers:
237        updated_list += ['custom_dns']
238      else:
239        updated_list += ['custom_dns.ds_records']
240    update_mask = ','.join(updated_list)
241
242    # pylint: disable=line-too-long
243    req = self.messages.DomainsProjectsLocationsRegistrationsConfigureDnsSettingsRequest(
244        registration=registration_ref.RelativeName(),
245        configureDnsSettingsRequest=self.messages.ConfigureDnsSettingsRequest(
246            dnsSettings=dns_settings,
247            updateMask=update_mask,
248            validateOnly=validate_only))
249
250    return self._service.ConfigureDnsSettings(req)
251
252  def ConfigureContacts(self, registration_ref, contacts, contact_privacy,
253                        public_contacts_ack, validate_only):
254    """Calls ConfigureContactSettings method.
255
256    Args:
257      registration_ref: Registration resource reference.
258      contacts: New Contacts.
259      contact_privacy: New Contact privacy.
260      public_contacts_ack: Whether the user accepted public privacy.
261      validate_only: validate_only flag.
262
263    Returns:
264      Long Running Operation reference.
265    """
266    updated_list = []
267    if contact_privacy:
268      updated_list += ['privacy']
269
270    if contacts is None:
271      contact_settings = self.messages.ContactSettings(privacy=contact_privacy)
272    else:
273      contact_settings = self.messages.ContactSettings(
274          privacy=contact_privacy,
275          registrantContact=contacts.registrantContact,
276          adminContact=contacts.adminContact,
277          technicalContact=contacts.technicalContact)
278
279      if contacts.registrantContact:
280        updated_list += ['registrant_contact']
281      if contacts.adminContact:
282        updated_list += ['admin_contact']
283      if contacts.technicalContact:
284        updated_list += ['technical_contact']
285
286    update_mask = ','.join(updated_list)
287
288    notices = []
289    if public_contacts_ack:
290      notices = [
291          self.messages.ConfigureContactSettingsRequest
292          .ContactNoticesValueListEntryValuesEnum
293          .PUBLIC_CONTACT_DATA_ACKNOWLEDGEMENT
294      ]
295
296    # pylint: disable=line-too-long
297    req = self.messages.DomainsProjectsLocationsRegistrationsConfigureContactSettingsRequest(
298        registration=registration_ref.RelativeName(),
299        configureContactSettingsRequest=self.messages
300        .ConfigureContactSettingsRequest(
301            contactSettings=contact_settings,
302            updateMask=update_mask,
303            contactNotices=notices,
304            validateOnly=validate_only))
305
306    return self._service.ConfigureContactSettings(req)
307
308  def ConfigureRegistrantEmail(self, registration_ref, registrant_email):
309    """Sets a registrant contact.
310
311    This resends registrant email confirmation.
312    It's done by updating registrant email to the current value.
313
314    Args:
315      registration_ref: a Resource reference to a
316        domains.projects.locations.registrations resource.
317      registrant_email: The registrant email.
318
319    Returns:
320      Operation: the long running operation to configure contacts registration.
321    """
322    contact_settings = self.messages.ContactSettings(
323        registrantContact=self.messages.Contact(email=registrant_email))
324
325    # pylint: disable=line-too-long
326    req = self.messages.DomainsProjectsLocationsRegistrationsConfigureContactSettingsRequest(
327        registration=registration_ref.RelativeName(),
328        configureContactSettingsRequest=self.messages
329        .ConfigureContactSettingsRequest(
330            contactSettings=contact_settings,
331            updateMask='registrant_contact.email'))
332
333    return self._service.ConfigureContactSettings(req)
334
335  def RetrieveRegisterParameters(self, parent_ref, domain):
336    # pylint: disable=line-too-long
337    request = self.messages.DomainsProjectsLocationsRegistrationsRetrieveRegisterParametersRequest(
338        location=parent_ref.RelativeName(), domainName=domain)
339    return self._service.RetrieveRegisterParameters(request).registerParameters
340
341  def SearchDomains(self, parent_ref, query):
342    # pylint: disable=line-too-long
343    request = self.messages.DomainsProjectsLocationsRegistrationsSearchDomainsRequest(
344        location=parent_ref.RelativeName(), query=query)
345    return self._service.SearchDomains(request).registerParameters
346