def _FormatFromParts(): """Returns the formatted time from broken down time parts in r. Raises: TypeError: For invalid time part errors. ValueError: For time conversion errors or not enough valid time parts. Returns: The formatted time from broken down time parts in r. """ valid = 0 parts = [] now = datetime.datetime.now(tz_in) for part in ('year', 'month', 'day', 'hour', 'minute', 'second'): value = resource_property.Get(r, [part], None) if value is None: # Missing parts default to now. value = getattr(now, part, 0) else: valid += 1 parts.append(int(value)) # The last value is microseconds. Add in any subsecond parts but don't count # them in the validity check. parts.append(0) for i, part in enumerate(['nanosecond', 'microsecond', 'millisecond']): value = resource_property.Get(r, [part], None) if value is not None: parts[-1] += int(int(value) * 1000**(i - 1)) # year&month&day or hour&minute&second would be OK, "3" covers those and any # combination of 3 non-subsecond date/time parts. if valid < 3: raise ValueError parts.append(tz_in) dt = datetime.datetime(*parts) return times.FormatDateTime(dt, format, tz_out)
def Tap(self, resource): """Returns the next slice item in resource. Args: resource: The resource to flatten. Returns: True if the next slice is not a list, False if there are no more items, or Injector(resource) which is the resource with the next slice flattened. """ if self._items is None: # Modify a serialized copy of resource. self._resource = resource_projector.MakeSerializable(resource) self._items = resource_property.Get(self._resource, self._key) if not isinstance(self._items, list): item = self._items self._items = None return peek_iterable.TapInjector(item, replace=True) if not self._items: self._items = None return False item = self._items.pop(0) if self._parent_key: parent = resource_property.Get(self._resource, self._parent_key) else: parent = self._resource parent[self._child_name] = item return peek_iterable.TapInjector(self._resource)
def TransformUri(r, projection, undefined='.'): """Gets the resource URI. Args: r: A JSON-serializable object. projection: The parent ProjectionSpec. undefined: Returns this if a the URI for r cannot be determined. Returns: The URI for r or undefined if not defined. """ names = ('selfLink', 'SelfLink') def _GetAttr(attr): """Returns the string value for attr or None if the value is not a string. Args: attr: The attribute object to get the value from. Returns: The string value for attr or None if the value is not a string. """ try: attr = attr() except TypeError: pass return attr if isinstance(attr, (basestring, buffer)) else None if isinstance(r, (basestring, buffer)): if r.startswith('https://'): return r elif r: # Low hanging fruit first. for name in names: uri = _GetAttr(resource_property.Get(r, [name], None)) if uri: return uri if projection: collection_func = projection.symbols.get('collection', None) collection = collection_func(r) if collection_func else None if collection: # Generate the URI from the collection and a few params. instance = _GetAttr( resource_property.Get(r, ['instance'], None)) project = _GetAttr(resource_property.Get(r, ['project'], None)) try: uri = resources.Create(collection, project=project, instance=instance).SelfLink() except (resources.InvalidCollectionException, core_apis.UnknownAPIError, resources.UnknownCollectionException): uri = None if uri: return uri return undefined
def Evaluate(self, obj): """Serializes/projects/transforms obj. A default or empty projection expression simply converts a resource object to a JSON-serializable copy of the object. Args: obj: An object. Returns: A JSON-serializeable object containing only the key values selected by the projection. The return value is a deep copy of the object: changes to the input object do not affect the JSON-serializable copy. """ self._transforms_enabled = self._transforms_enabled_attribute if not self._by_columns or not self._columns: if self._columns: self._retain_none_values = False flag = self._projection.DEFAULT else: flag = self._projection.PROJECT return self._Project(obj, self._projection.Tree(), flag) obj = self._Project(obj, self._projection.GetEmpty(), self._projection.PROJECT) if self._transforms_enabled_attribute is None: # By-column formats enable transforms by default. self._transforms_enabled = True columns = [] for column in self._columns: val = resource_property.Get(obj, column.key) if column.key else obj if (column.attribute.transform and self._TransformIsEnabled(column.attribute.transform)): val = column.attribute.transform.Evaluate(val) columns.append(val) return columns
def Evaluate(self, obj): """Serializes/projects/transforms one or more objects. A default or empty projection expression simply converts a resource object to a JSON-serializable copy of the object. Args: obj: An object. Returns: A JSON-serializeable object containing only the key values selected by the projection. The return value is a deep copy of the object: changes to the input object do not affect the JSON-serializable copy. """ if not self._by_columns or not self._projection.Columns(): flag = (self._projection.DEFAULT if self._projection.Columns() else self._projection.PROJECT) return self._Project(obj, self._projection.Tree(), flag) columns = [] for column in self._projection.Columns(): val = resource_property.Get(obj, column.key) if column.key else obj transform = column.attribute.transform if transform: val = transform.func(val, *transform.args, **transform.kwargs) columns.append(val) return columns
def get_field(self, field_name, unused_args, unused_kwargs): r"""Returns the value of field_name for string.Formatter.format(). Args: field_name: The format string field name to get in the form name - the value of name in the payload, '' if undefined name?FORMAT - if name is non-empty then re-formats with FORMAT, where {?} is the value of name. For example, if name=NAME then {name?\nname is "{?}".} expands to '\nname is "NAME".'. .a.b.c - the value of a.b.c in the JSON decoded payload contents. For example, '{.errors.reason?[{?}]}' expands to [REASON] if .errors.reason is defined. unused_args: Ignored. unused_kwargs: Ignored. Returns: The value of field_name for string.Formatter.format(). """ field_name = _Expand(field_name) if field_name == '?': return self._value, field_name parts = field_name.split('?', 1) subparts = parts.pop(0).split(':', 1) name = subparts.pop(0) printer_format = subparts.pop(0) if subparts else None recursive_format = parts.pop(0) if parts else None if '.' in name: if name.startswith('.'): # Only check self.content. check_payload_attributes = False name = name[1:] else: # Check the payload attributes first, then self.content. check_payload_attributes = True key = resource_lex.Lexer(name).Key() content = self.content if check_payload_attributes and key: value = self.__dict__.get(key[0], None) if value: content = {key[0]: value} value = resource_property.Get(content, key, None) elif name: value = self.__dict__.get(name, None) else: value = None if not value and not isinstance(value, (int, float)): return '', name if printer_format or not isinstance( value, (six.text_type, six.binary_type, float) + six.integer_types): buf = io.StringIO() resource_printer.Print(value, printer_format or 'default', out=buf, single=True) value = buf.getvalue().strip() if recursive_format: self._value = value value = self.format(_Expand(recursive_format)) # pytype: disable=wrong-arg-types return value, name
def TransformUri(r, undefined='.'): """Gets the resource URI. Args: r: A JSON-serializable object. undefined: Returns this if a the URI for r cannot be determined. Returns: The URI for r or undefined if not defined. """ def _GetAttr(attr): """Returns the string value for attr or None if the value is not a string. Args: attr: The attribute object to get the value from. Returns: The string value for attr or None if the value is not a string. """ try: attr = attr() except TypeError: pass return attr if isinstance(attr, (basestring, buffer)) else None if isinstance(r, (basestring, buffer)): if r.startswith('https://'): return r elif r: for name in ('selfLink', 'SelfLink'): uri = _GetAttr(resource_property.Get(r, [name], None)) if uri: return uri return undefined
def Evaluate(self, obj): """Serializes/projects/transforms one or more objects. A default or empty projection expression simply converts a resource object to a JSON-serializable copy of the object. Args: obj: An object. Returns: A JSON-serializeable object containing only the key values selected by the projection. The return value is a deep copy of the object: changes to the input object do not affect the JSON-serializable copy. """ self._transforms_enabled = self._transforms_enabled_attribute if not self._by_columns or not self._projection.Columns(): flag = (self._projection.DEFAULT if self._projection.Columns() else self._projection.PROJECT) return self._Project(obj, self._projection.Tree(), flag) if self._transforms_enabled is None: # Pretty-print formats enable transforms by default. self._transforms_enabled = True columns = [] for column in self._projection.Columns(): val = resource_property.Get(obj, column.key) if column.key else obj if column.attribute.transform: val = self._ProjectTransform(val, column.attribute.transform) columns.append(val) return columns
def Evaluate(self, obj): """Evaluate a term node. Args: obj: The resource object to evaluate. Returns: The value of the operator applied to the key value and operand. """ value = resource_property.Get(obj, self._key) if self._transform: try: if self._key: value = self._transform(value, *self._args) else: value = self._transform(*self._args) except (AttributeError, TypeError, ValueError): value = None # Each try/except attempts a different combination of value/operand # numeric and string conversions. if self._operand.numeric_value is not None: try: return self.Apply(float(value), self._operand.numeric_value) except (TypeError, ValueError): pass try: return self.Apply(value, self._operand.string_value) except (AttributeError, ValueError): return False except TypeError: if isinstance(value, basestring): return False try: return self.Apply(str(value), self._operand.string_value) except TypeError: return False
def Evaluate(self, obj): """Evaluate a term node. Args: obj: The resource object to evaluate. Returns: The value of the operator applied to the key value and operand. """ value = resource_property.Get(obj, self._key) if self._transform: value = self._transform.Evaluate(value) # Arbitrary choice: value == [] => values = [[]] resource_values = value if value and isinstance(value, list) else [ value ] values = [] for value in resource_values: if value: try: value = self._normalize(value) except (TypeError, ValueError): pass values.append(value) if self._operand.list_value: operands = self._operand.list_value else: operands = [self._operand] # Check for any match in all value X operand combinations. for value in values: for operand in operands: # Each try/except attempts a different combination of value/operand # numeric and string conversions. if operand.numeric_value is not None: try: if self.Apply(float(value), operand.numeric_value): return True # Both value and operand are numbers - don't try as strings below. continue except (TypeError, ValueError): pass try: if self.Apply(value, operand.string_value): return True except (AttributeError, ValueError): pass except TypeError: if not isinstance(value, (basestring, dict, list)): try: if self.Apply(unicode(value), operand.string_value): return True except TypeError: pass return False
def get_field(self, field_name, unused_args, unused_kwargs): r"""Returns the value of field_name for string.Formatter.format(). Args: field_name: The format string field name to get in the form name - the value of name in the payload, '' if undefined name?FORMAT - if name is non-empty then re-formats with FORMAT, where {?} is the value of name. For example, if name=NAME then {name?\nname is "{?}".} expands to '\nname is "NAME".'. ':' may not appear in FORMAT, use {?COLON?} instead. .a.b.c - the value of a.b.c in the JSON decoded payload contents. For example, '{.errors.reason?[{?}]}' expands to [REASON] if .errors.reason is defined. unused_args: Ignored. unused_kwargs: Ignored. Returns: The value of field_name for string.Formatter.format(). """ if field_name.startswith('?'): if field_name == '?': return self._value, field_name if field_name == '?COLON?': return ':', field_name parts = field_name.split('?', 1) name = parts.pop(0) fmt = parts.pop(0) if parts else None if '.' in name: if name.startswith('.'): # Only check self.content. check_payload_attributes = False name = name[1:] else: # Check the payload attributes first, then self.content. check_payload_attributes = True key = resource_lex.Lexer(name).Key() content = self.content if check_payload_attributes and key: value = self.__dict__.get(key[0], None) if value: content = {key[0]: value} value = resource_property.Get(content, key, '') elif name: value = self.__dict__.get(name, '') else: value = '' if not value and not isinstance(value, (int, float)): return '', name if not isinstance(value, (basestring, int, float)): buf = StringIO.StringIO() resource_printer.Print(value, 'default', out=buf, single=True) value = buf.getvalue().strip() if fmt: self._value = value value = self.format(fmt) return value, name
def _GetKey(r, key): """Returns the value for key in r that can be compared with None.""" value = resource_property.Get(r, key, None) # Some types (datetime for example) preclude comparisons with None. # This converts the value to a string and uses that ordering. try: assert None < value return value except (AssertionError, TypeError): return six.text_type(value)
def next(self): """Returns the next item in the aggregated list.""" while self._index >= len(self._list): obj = self._NextItem() self._list = resource_property.Get(obj, self._key) or [] if not isinstance(self._list, list): self._list = [self._list] self._index = 0 item = self._list[self._index] self._index += 1 return item
def _GetKeyValue(r, key, undefined=None): """Returns the value for key in r. Args: r: The resource object. key: The dotted attribute name string. undefined: This is returned if key is not in r. Returns: The value for key in r. """ return resource_property.Get(r, _GetParsedKey(key), undefined)
def _Dimension(d): """Gets the resolution dimension for d. Args: d: The dimension name substring to get. Returns: The resolution dimension matching d or None. """ for m in mem: if d in m: return resource_property.Get(r, [mem[d]], None) return None
def _SortResources(self, keys, reverse): """_AddSortByTap helper that sorts the resources by keys. Args: keys: The ordered list of parsed resource keys from highest to lowest precedence. reverse: Sort by the keys in descending order if True, otherwise ascending. """ self._resources = sorted( self._resources, key=lambda r: [resource_property.Get(r, k) for k in keys], reverse=reverse)
def _GetKeyValue(r, key, undefined=None): """Returns the value for key in r. Args: r: The resource object. key: The dotted attribute name. undefined: This is returned if key is not in r. Returns: The value for key in r. """ # Circular dependency on resource_lex for # parsed_key = resource_lex.Lexer(key).Key() # so we settle for simple keys here. parsed_key = key.split('.') return resource_property.Get(r, parsed_key, undefined)
def TransformFirstOf(r, *args): """Returns the first non-empty .name attribute value for name in args. Args: r: A JSON-serializable object. *args: Names to check for resource attribute values, Returns: The first non-empty r.name value for name in args, '' otherwise. Example: x.firstof(bar_foo, barFoo, BarFoo, BAR_FOO) will check x.bar_foo, x.barFoo, x.BarFoo, and x.BAR_FOO in order for the first non-empty value. """ for name in args: v = resource_property.Get(r, [name], None) if v is not None: return v return ''
def TransformGroup(r, *keys): """Formats a [...] grouped list. Each group is enclosed in [...]. The first item separator is ':', subsequent separators are ','. [item1] [item1] ... [item1: item2] ... [item1: item2] [item1: item2, item3] ... [item1: item2, item3] Args: r: A JSON-serializable object. *keys: Optional attribute keys to select from the list. Otherwise the string value of each list item is selected. Returns: The [...] grouped formatted list, [] if r is empty. """ if not r: return '[]' buf = StringIO.StringIO() sep = None parsed_keys = [_GetParsedKey(key) for key in keys] for item in r: if sep: buf.write(sep) else: sep = ' ' if not parsed_keys: buf.write('[{0}]'.format(unicode(item))) else: buf.write('[') sub = None for key in parsed_keys: if sub: buf.write(sub) sub = ', ' else: sub = ': ' value = resource_property.Get(item, key, None) if value is not None: buf.write(unicode(value)) buf.write(']') return buf.getvalue()
def _Synthesize(r): """Synthesize a new resource list from the original resource r. Args: r: The original resource. Returns: The synthesized resource list. """ synthesized_resource_list = [] for schema in schemas: synthesized_resource = {} for attr in schema: name, key, literal = attr value = resource_property.Get(r, key, None) if key else literal if name: synthesized_resource[name] = value elif isinstance(value, dict): synthesized_resource.update(value) synthesized_resource_list.append(synthesized_resource) return synthesized_resource_list
def Evaluate(self, obj): """Evaluate a term node. Args: obj: The resource object to evaluate. Returns: The value of the operator applied to the key value and operand. """ value = resource_property.Get(obj, self._key) if self._transform: try: value = self._transform.Evaluate(value) except (AttributeError, TypeError, ValueError): value = None if self._operand.list_value: operands = self._operand.list_value else: operands = [self._operand] for operand in operands: # Each try/except attempts a different combination of value/operand # numeric and string conversions. if operand.numeric_value is not None: try: return self.Apply(float(value), operand.numeric_value) except (TypeError, ValueError): pass try: if self.Apply(value, operand.string_value): return True except (AttributeError, ValueError): pass except TypeError: if not isinstance(value, basestring): try: if self.Apply(unicode(value), operand.string_value): return True except TypeError: pass return False
def Evaluate(self, obj): """Evaluate a term node. Args: obj: The resource object to evaluate. Returns: The value of the operator applied to the key value and operand. """ value = resource_property.Get(obj, self._key) if self._transform: try: value = (self._transform(value, *self._args) if self._key else self._transform(*self._args)) except (AttributeError, TypeError, ValueError): value = None if self._operand.numeric_value is not None: try: return self.Apply(float(value), self._operand.numeric_value) except (TypeError, ValueError): pass try: return self.Apply(value, self._operand.string_value) except (AttributeError, TypeError, ValueError): return False
def _GetField(self, name): """Gets the value corresponding to name in self.content or class attributes. If `name` starts with a period, treat it as a key in self.content and get the corresponding value. Otherwise get the value of the class attribute named `name` first and fall back to checking keys in self.content. Args: name (str): The name of the attribute to return the value of. Returns: A tuple where the first value is `name` with any leading periods dropped, and the second value is the value of a class attribute or key in self.content. """ if '.' in name: if name.startswith('.'): # Only check self.content. check_payload_attributes = False name = name[1:] else: # Check the payload attributes first, then self.content. check_payload_attributes = True key = resource_lex.Lexer(name).Key() content = self.content if check_payload_attributes and key: value = self.__dict__.get(key[0], None) if value: content = {key[0]: value} value = resource_property.Get(content, key, None) elif name: value = self.__dict__.get(name, None) else: value = None return name, value
def RunBaseCreateCommand(args): """Creates a new Cloud SQL instance. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: A dict object representing the operations resource describing the create operation if the create was successful. Raises: HttpException: A http error response was received while executing api request. ToolException: An error other than http error occured while executing the command. """ client = api_util.SqlClient(api_util.API_VERSION_DEFAULT) sql_client = client.sql_client sql_messages = client.sql_messages validate.ValidateInstanceName(args.instance) instance_ref = client.resource_parser.Parse( args.instance, params={'project': properties.VALUES.core.project.GetOrFail}, collection='sql.instances') instance_resource = instances.InstancesV1Beta4.ConstructInstanceFromArgs( sql_messages, args, instance_ref=instance_ref) if args.pricing_plan == 'PACKAGE': if not console_io.PromptContinue( 'Charges will begin accruing immediately. Really create Cloud ' 'SQL instance?'): raise exceptions.ToolException('canceled by the user.') operation_ref = None try: result_operation = sql_client.instances.Insert(instance_resource) operation_ref = client.resource_parser.Create( 'sql.operations', operation=result_operation.name, project=instance_ref.project) if args.async: if not args.IsSpecified('format'): args.format = 'default' return sql_client.operations.Get( sql_messages.SqlOperationsGetRequest( project=operation_ref.project, operation=operation_ref.operation)) operations.OperationsV1Beta4.WaitForOperation( sql_client, operation_ref, 'Creating Cloud SQL instance') log.CreatedResource(instance_ref) new_resource = sql_client.instances.Get( sql_messages.SqlInstancesGetRequest( project=instance_ref.project, instance=instance_ref.instance)) return new_resource except apitools_exceptions.HttpError as error: log.debug('operation : %s', str(operation_ref)) exc = exceptions.HttpException(error) if resource_property.Get(exc.payload.content, resource_lex.ParseKey('error.errors[0].reason'), None) == 'errorMaxInstancePerLabel': msg = resource_property.Get(exc.payload.content, resource_lex.ParseKey('error.message'), None) raise exceptions.HttpException(msg) raise
def TransformDate(r, format='%Y-%m-%dT%H:%M:%S', unit=1, undefined='', tz=None, tz_default=None): """Formats the resource as a strftime() format. Args: r: A timestamp number or an object with 3 or more of these fields: year, month, day, hour, minute, second, millisecond, microsecond, nanosecond. format: The strftime(3) format. unit: If the resource is a Timestamp then divide by _unit_ to yield seconds. undefined: Returns this value if the resource is not a valid time. tz: Return the time relative to the tz timezone if specified, the explicit timezone in the resource if it has one, otherwise the local timezone. For example, ...date(tz=EST5EDT, tz_default=UTC). tz_default: The default timezone if the resource does not have a timezone suffix. Returns: The strftime() date format for r or undefined if r does not contain a valid time. """ # Check if r has an isoformat() method. try: r = r.isoformat() except (AttributeError, TypeError, ValueError): pass tz_in = times.GetTimeZone(tz_default) if tz_default else None # Check if r is a timestamp. try: timestamp = float(r) / float(unit) dt = times.GetDateTimeFromTimeStamp(timestamp, tz_in) return times.FormatDateTime(dt, format) except (TypeError, ValueError): pass # Check if r is a serialized datetime object. original_repr = resource_property.Get(r, ['datetime'], None) if original_repr and isinstance(original_repr, basestring): r = original_repr tz_out = times.GetTimeZone(tz) if tz else None # Check if r is a date/time string. try: dt = times.ParseDateTime(r, tz_in) return times.FormatDateTime(dt, format, tz_out) except (AttributeError, ImportError, TypeError, ValueError): pass def _FormatFromParts(): """Returns the formatted time from broken down time parts in r. Raises: TypeError: For invalid time part errors. ValueError: For time conversion errors or not enough valid time parts. Returns: The formatted time from broken down time parts in r. """ valid = 0 parts = [] now = datetime.datetime.now(tz_in) for part in ('year', 'month', 'day', 'hour', 'minute', 'second'): value = resource_property.Get(r, [part], None) if value is None: # Missing parts default to now. value = getattr(now, part, 0) else: valid += 1 parts.append(int(value)) # The last value is microseconds. Add in any subsecond parts but don't count # them in the validity check. parts.append(0) for i, part in enumerate(['nanosecond', 'microsecond', 'millisecond']): value = resource_property.Get(r, [part], None) if value is not None: parts[-1] += int(int(value) * 1000**(i - 1)) # year&month&day or hour&minute&second would be OK, "3" covers those and any # combination of 3 non-subsecond date/time parts. if valid < 3: raise ValueError parts.append(tz_in) dt = datetime.datetime(*parts) return times.FormatDateTime(dt, format, tz_out) try: return _FormatFromParts() except (TypeError, ValueError): pass # Does anyone really know what time it is? return undefined
def RunBaseCreateCommand(args, release_track): """Creates a new Cloud SQL instance. Args: args: argparse.Namespace, The arguments that this command was invoked with. release_track: base.ReleaseTrack, the release track that this was run under. Returns: A dict object representing the operations resource describing the create operation if the create was successful. Raises: HttpException: A http error response was received while executing api request. RequiredArgumentException: A required argument was not supplied by the user, such as omitting --root-password on a SQL Server instance. ArgumentError: An argument supplied by the user was incorrect, such as attempting to create a V1 instance. """ client = common_api_util.SqlClient(common_api_util.API_VERSION_DEFAULT) sql_client = client.sql_client sql_messages = client.sql_messages validate.ValidateInstanceName(args.instance) instance_ref = client.resource_parser.Parse( args.instance, params={'project': properties.VALUES.core.project.GetOrFail}, collection='sql.instances') # Get the region, tier, and database version from the master if these fields # are not specified. # TODO(b/64266672): Remove once API does not require these fields. if args.IsSpecified('master_instance_name'): master_instance_ref = client.resource_parser.Parse( args.master_instance_name, params={'project': properties.VALUES.core.project.GetOrFail}, collection='sql.instances') try: master_instance_resource = sql_client.instances.Get( sql_messages.SqlInstancesGetRequest( project=instance_ref.project, instance=master_instance_ref.instance)) except apitools_exceptions.HttpError as error: # TODO(b/64292220): Remove once API gives helpful error message. log.debug('operation : %s', six.text_type(master_instance_ref)) exc = exceptions.HttpException(error) if resource_property.Get(exc.payload.content, resource_lex.ParseKey('error.errors[0].reason'), None) == 'notAuthorized': msg = ('You are either not authorized to access the master instance or ' 'it does not exist.') raise exceptions.HttpException(msg) raise if not args.IsSpecified('region'): args.region = master_instance_resource.region if not args.IsSpecified('database_version'): args.database_version = master_instance_resource.databaseVersion.name if not args.IsSpecified('tier') and master_instance_resource.settings: args.tier = master_instance_resource.settings.tier # Check for CMEK usage; warn the user about replica inheriting the setting. if master_instance_resource.diskEncryptionConfiguration: command_util.ShowCmekWarning('replica', 'the master instance') # --root-password is required when creating SQL Server instances if args.IsSpecified('database_version') and args.database_version.startswith( 'SQLSERVER') and not args.IsSpecified('root_password'): raise exceptions.RequiredArgumentException( '--root-password', '`--root-password` is required when creating SQL Server instances.') instance_resource = ( command_util.InstancesV1Beta4.ConstructCreateInstanceFromArgs( sql_messages, args, instance_ref=instance_ref, release_track=release_track)) # TODO(b/122660263): Remove when V1 instances are no longer supported. # V1 instances are deprecated. # Note that the exception type is intentionally vague because the user may not # have directly supplied the offending argument. For example, creating a read # replica defaults its tier to that of its master. if api_util.IsInstanceV1(sql_messages, instance_resource): raise sql_exceptions.ArgumentError( 'First Generation instances can no longer be created.') operation_ref = None try: result_operation = sql_client.instances.Insert(instance_resource) operation_ref = client.resource_parser.Create( 'sql.operations', operation=result_operation.name, project=instance_ref.project) if args.async_: if not args.IsSpecified('format'): args.format = 'default' return sql_client.operations.Get( sql_messages.SqlOperationsGetRequest( project=operation_ref.project, operation=operation_ref.operation)) operations.OperationsV1Beta4.WaitForOperation( sql_client, operation_ref, 'Creating Cloud SQL instance', # TODO(b/138403566): Remove the override once we improve creation times. max_wait_seconds=680) log.CreatedResource(instance_ref) new_resource = sql_client.instances.Get( sql_messages.SqlInstancesGetRequest( project=instance_ref.project, instance=instance_ref.instance)) return new_resource except apitools_exceptions.HttpError as error: log.debug('operation : %s', six.text_type(operation_ref)) exc = exceptions.HttpException(error) if resource_property.Get(exc.payload.content, resource_lex.ParseKey('error.errors[0].reason'), None) == 'errorMaxInstancePerLabel': msg = resource_property.Get(exc.payload.content, resource_lex.ParseKey('error.message'), None) raise exceptions.HttpException(msg) raise
def RunBaseCreateCommand(args, release_track): """Creates a new Cloud SQL instance. Args: args: argparse.Namespace, The arguments that this command was invoked with. release_track: base.ReleaseTrack, the release track that this was run under. Returns: A dict object representing the operations resource describing the create operation if the create was successful. Raises: HttpException: A http error response was received while executing api request. """ client = common_api_util.SqlClient(common_api_util.API_VERSION_DEFAULT) sql_client = client.sql_client sql_messages = client.sql_messages validate.ValidateInstanceName(args.instance) instance_ref = client.resource_parser.Parse( args.instance, params={'project': properties.VALUES.core.project.GetOrFail}, collection='sql.instances') # Get the region, tier, and database version from the main if these fields # are not specified. # TODO(b/64266672): Remove once API does not require these fields. if args.IsSpecified('main_instance_name'): main_instance_ref = client.resource_parser.Parse( args.main_instance_name, params={'project': properties.VALUES.core.project.GetOrFail}, collection='sql.instances') try: main_instance_resource = sql_client.instances.Get( sql_messages.SqlInstancesGetRequest( project=instance_ref.project, instance=main_instance_ref.instance)) except apitools_exceptions.HttpError as error: # TODO(b/64292220): Remove once API gives helpful error message. log.debug('operation : %s', str(main_instance_ref)) exc = exceptions.HttpException(error) if resource_property.Get( exc.payload.content, resource_lex.ParseKey('error.errors[0].reason'), None) == 'notAuthorized': msg = ( 'You are either not authorized to access the main instance or ' 'it does not exist.') raise exceptions.HttpException(msg) raise if not args.IsSpecified('region'): args.region = main_instance_resource.region if not args.IsSpecified('database_version'): args.database_version = main_instance_resource.databaseVersion if not args.IsSpecified('tier') and main_instance_resource.settings: args.tier = main_instance_resource.settings.tier # Check for CMEK usage; warn the user about replica inheriting the setting. if main_instance_resource.diskEncryptionConfiguration: command_util.ShowCmekWarning('replica', 'the main instance') instance_resource = ( command_util.InstancesV1Beta4.ConstructCreateInstanceFromArgs( sql_messages, args, instance_ref=instance_ref, release_track=release_track)) # TODO(b/122660263): Remove when V1 instances are no longer supported. # V1 instances are deprecated. Prompt to continue if one is being created. if api_util.IsInstanceV1(instance_resource): log.warning( 'First Generation instances will be automatically upgraded ' 'to Second Generation starting March 4th, 2020, and First Generation ' 'will be fully decommissioned on March 25, 2020. We recommend you ' 'create a Second Generation instance.') console_io.PromptContinue(cancel_on_no=True) if args.pricing_plan == 'PACKAGE': console_io.PromptContinue( 'Charges will begin accruing immediately. Really create Cloud ' 'SQL instance?', cancel_on_no=True) operation_ref = None try: result_operation = sql_client.instances.Insert(instance_resource) operation_ref = client.resource_parser.Create( 'sql.operations', operation=result_operation.name, project=instance_ref.project) if args. async: if not args.IsSpecified('format'): args.format = 'default' return sql_client.operations.Get( sql_messages.SqlOperationsGetRequest( project=operation_ref.project, operation=operation_ref.operation)) operations.OperationsV1Beta4.WaitForOperation( sql_client, operation_ref, 'Creating Cloud SQL instance') log.CreatedResource(instance_ref) new_resource = sql_client.instances.Get( sql_messages.SqlInstancesGetRequest( project=instance_ref.project, instance=instance_ref.instance)) return new_resource except apitools_exceptions.HttpError as error: log.debug('operation : %s', str(operation_ref)) exc = exceptions.HttpException(error) if resource_property.Get( exc.payload.content, resource_lex.ParseKey('error.errors[0].reason'), None) == 'errorMaxInstancePerLabel': msg = resource_property.Get(exc.payload.content, resource_lex.ParseKey('error.message'), None) raise exceptions.HttpException(msg) raise
def _AddRecord(self, record, delimit=True): for col, printer in self.columns: printer.Print(resource_property.Get(record, col.key))
def RunSubTest(self, r, key, default=None): return resource_property.Get(r, key, default)
def Run(self, args): """Creates a new Cloud SQL instance. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: A dict object representing the operations resource describing the create operation if the create was successful. Raises: HttpException: A http error response was received while executing api request. ToolException: An error other than http error occured while executing the command. """ sql_client = self.context['sql_client'] sql_messages = self.context['sql_messages'] resources = self.context['registry'] validate.ValidateInstanceName(args.instance) instance_ref = resources.Parse(args.instance, collection='sql.instances') instance_resource = instances.InstancesV1Beta4.ConstructInstanceFromArgs( sql_messages, args, instance_ref=instance_ref) if args.pricing_plan == 'PACKAGE': if not console_io.PromptContinue( 'Charges will begin accruing immediately. Really create Cloud ' 'SQL instance?'): raise exceptions.ToolException('canceled by the user.') operation_ref = None try: result_operation = sql_client.instances.Insert(instance_resource) operation_ref = resources.Create( 'sql.operations', operation=result_operation.name, project=instance_ref.project) if args.async: return sql_client.operations.Get( sql_messages.SqlOperationsGetRequest( project=operation_ref.project, operation=operation_ref.operation)) operations.OperationsV1Beta4.WaitForOperation( sql_client, operation_ref, 'Creating Cloud SQL instance') log.CreatedResource(instance_ref) new_resource = sql_client.instances.Get( sql_messages.SqlInstancesGetRequest( project=instance_ref.project, instance=instance_ref.instance)) cache = remote_completion.RemoteCompletion() cache.AddToCache(instance_ref.SelfLink()) return new_resource except apitools_exceptions.HttpError as error: log.debug('operation : %s', str(operation_ref)) exc = exceptions.HttpException(error) if resource_property.Get(exc.payload.content, resource_lex.ParseKey('error.errors[0].reason'), None) == 'errorMaxInstancePerLabel': msg = resource_property.Get(exc.payload.content, resource_lex.ParseKey('error.message'), None) raise exceptions.HttpException(msg) raise