Skip to content

Commit

Permalink
[Generator] (fix) Support date-time format enrichment (#2867)
Browse files Browse the repository at this point in the history
* [Generator] (fix) String with the 'date-time' format

Strings with the 'format' fields set to 'date-time' were previously read as strings.
Meanwhile the Go client automatically converts them to `*time.Time`.
Such fields are now properly converted back to strings when updating the state.

* [Generator] (tidy) formatted file

* [Generator] (doc) Added documentation to new function/filter

* [Generator] (feat) Modified the previously added filter to be more generic

added a printing filter

* [Generator] (tidy) renamed filter
  • Loading branch information
Supam authored Feb 26, 2025
1 parent dff9be9 commit e308b50
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 8 deletions.
26 changes: 26 additions & 0 deletions .generator/src/generator/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def sanitize_description(description):
def escape_reserved_keyword(word):
"""
Escape reserved language keywords like openapi generator does it
:param word: Word to escape
:return: The escaped word if it was a reserved keyword, the word unchanged otherwise
"""
Expand Down Expand Up @@ -139,3 +140,28 @@ def get_terraform_schema_type(schema):
"object": "Block",
None: "String",
}[schema.get("type")]


def go_to_terraform_type_formatter(name: str, schema: dict) -> str:
"""
This function is intended to be used in the Jinja2 templates.
It was made to support the format enrichment of the OpenAPI schema.
The format enrichment allows for a more appropriate Go type to be used in the provider (eg: string + date-time enrichment -> time.Time).
However when updating the state we wish to use the primitive type that Terraform support instead.
Args:
name (str): The name of the variable to format.
schema (dict): OpenApi spec as a dictionary. May contain a "format" key.
Returns:
str: The string representation of the variable in Go.
"""
match schema.get("format"):
case "date-time":
return f"{variable_name(name)}.String()"
case "date":
return f"{variable_name(name)}.String()"
case "binary":
return f"string({variable_name(name)})"

# primitive types should fall through
case _:
return f"*{variable_name(name)}"
3 changes: 2 additions & 1 deletion .generator/src/generator/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ def load_environment(version: str) -> Environment:
env.filters["attribute_name"] = formatter.attribute_name
env.filters["camel_case"] = formatter.camel_case
env.filters["sanitize_description"] = formatter.sanitize_description

env.filters["snake_case"] = formatter.snake_case
env.filters["untitle_case"] = formatter.untitle_case
env.filters["variable_name"] = formatter.variable_name
env.filters["date_time_formatter"] = formatter.go_to_terraform_type_formatter
env.filters["parameter_schema"] = openapi.parameter_schema
env.filters["parameters"] = openapi.parameters
env.filters["is_json_api"] = openapi.is_json_api
env.filters["capitalize"] = utils.capitalize
env.filters["is_primitive"] = utils.is_primitive
env.filters["debug"] = utils.debug_filter
env.filters["response_type"] = type.get_type_for_response
env.filters["return_type"] = type.return_type
env.filters["tf_sort_params_by_type"] = type.tf_sort_params_by_type
Expand Down
10 changes: 5 additions & 5 deletions .generator/src/generator/templates/utils/state_helper.j2
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
{%- if not required %}
if {{ name|variable_name }}, ok := {{ baseAccessor }}.Get{{ name|camel_case }}Ok(); ok {
{%- endif %}
{%- if is_enum(schema) %}
{{ baseSetter }}.{{ name|camel_case }} = types.{{ get_terraform_schema_type(schema) }}Value({{ simple_type(schema) }}({% if required %}{{ baseAccessor }}.Get{{ name|camel_case }}(){% else %}*{{ name|variable_name }}{% endif %}))
{%- else %}
{{ baseSetter }}.{{ name|camel_case }} = types.{{ get_terraform_schema_type(schema) }}Value({% if required %}{{ baseAccessor }}.Get{{ name|camel_case }}(){% else %}*{{ name|variable_name }}{% endif %})
{%- endif %}
{%- if is_enum(schema) %}
{{ baseSetter }}.{{ name|camel_case }} = types.{{ get_terraform_schema_type(schema) }}Value({{ simple_type(schema) }}({% if required %}{{ baseAccessor }}.Get{{ name|camel_case }}(){% else %}{{name|date_time_formatter(schema)}}{% endif %}))
{%- else %}
{{ baseSetter }}.{{ name|camel_case }} = types.{{ get_terraform_schema_type(schema) }}Value({% if required %}{{ baseAccessor }}.Get{{ name|camel_case }}(){% else %}{{name|date_time_formatter(schema)}}{% endif %})
{%- endif %}
{%- if not required %}
}
{%- endif %}
Expand Down
13 changes: 11 additions & 2 deletions .generator/src/generator/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ def is_primitive(schema):
return True
return False


def is_required(schema, attr=None):
req_args =schema.get("required")
req_args = schema.get("required")
if req_args is None:
return False
if isinstance(req_args, bool):
Expand All @@ -58,12 +59,20 @@ def is_required(schema, attr=None):
return attr in req_args
raise ValueError(f"Invalid required value: {schema} ({attr})")


def is_computed(schema):
v = schema.get("readOnly", None) is True
return v


def is_enum(schema):
return "enum" in schema


def is_nullable(schema):
return schema.get("nullable", False)
return schema.get("nullable", False)


def debug_filter(value):
print(value)
return value

0 comments on commit e308b50

Please sign in to comment.