From c6c1aa7471e8908389a27e43706034f891ed6e15 Mon Sep 17 00:00:00 2001 From: Thibault Viennot Date: Mon, 24 Feb 2025 16:47:30 +0100 Subject: [PATCH 1/5] [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/src/generator/formatter.py | 6 ++++++ .generator/src/generator/setup.py | 2 +- .../src/generator/templates/utils/state_helper.j2 | 10 +++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.generator/src/generator/formatter.py b/.generator/src/generator/formatter.py index 9f3ba9aef..1f8bcbafa 100644 --- a/.generator/src/generator/formatter.py +++ b/.generator/src/generator/formatter.py @@ -139,3 +139,9 @@ def get_terraform_schema_type(schema): "object": "Block", None: "String", }[schema.get("type")] + + +def date_time_formatter(name: str, schema: dict): + if schema.get("format") == "date-time": + return f"{variable_name(name)}.String()" + return f"*{variable_name(name)}" diff --git a/.generator/src/generator/setup.py b/.generator/src/generator/setup.py index 4da36d794..ae4ae3a99 100644 --- a/.generator/src/generator/setup.py +++ b/.generator/src/generator/setup.py @@ -18,10 +18,10 @@ 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.date_time_formatter env.filters["parameter_schema"] = openapi.parameter_schema env.filters["parameters"] = openapi.parameters env.filters["is_json_api"] = openapi.is_json_api diff --git a/.generator/src/generator/templates/utils/state_helper.j2 b/.generator/src/generator/templates/utils/state_helper.j2 index 38d2bd920..3ea92aaad 100644 --- a/.generator/src/generator/templates/utils/state_helper.j2 +++ b/.generator/src/generator/templates/utils/state_helper.j2 @@ -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 %} From 012a0b7c9e5404faa9338cb4cefe14208f51d482 Mon Sep 17 00:00:00 2001 From: Thibault Viennot Date: Mon, 24 Feb 2025 17:03:51 +0100 Subject: [PATCH 2/5] [Generator] (tidy) formatted file --- .generator/src/generator/utils.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.generator/src/generator/utils.py b/.generator/src/generator/utils.py index 01558347c..3b62661ab 100644 --- a/.generator/src/generator/utils.py +++ b/.generator/src/generator/utils.py @@ -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): @@ -58,12 +59,15 @@ 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) \ No newline at end of file + return schema.get("nullable", False) From 343e8825425d9c5b757f2fb554befcf230d6b85c Mon Sep 17 00:00:00 2001 From: Thibault Viennot Date: Tue, 25 Feb 2025 09:31:56 +0100 Subject: [PATCH 3/5] [Generator] (doc) Added documentation to new function/filter --- .generator/src/generator/formatter.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.generator/src/generator/formatter.py b/.generator/src/generator/formatter.py index 1f8bcbafa..ca3bcb435 100644 --- a/.generator/src/generator/formatter.py +++ b/.generator/src/generator/formatter.py @@ -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 """ @@ -141,7 +142,18 @@ def get_terraform_schema_type(schema): }[schema.get("type")] -def date_time_formatter(name: str, schema: dict): +def date_time_formatter(name: str, schema: dict) -> str: + """ + This function is intended to be used in the Jinja2 templates. + It was made to support the "date-time" format of the OpenAPI schema. + Go's time.Time type is used to represent date-time values and should be instead transformed into a string. + 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. + """ + if schema.get("format") == "date-time": return f"{variable_name(name)}.String()" return f"*{variable_name(name)}" From 5541d48104e98b6aa69540683374651fe717e832 Mon Sep 17 00:00:00 2001 From: Thibault Viennot Date: Tue, 25 Feb 2025 14:25:06 +0100 Subject: [PATCH 4/5] [Generator] (feat) Modified the previously added filter to be more generic added a printing filter --- .generator/src/generator/formatter.py | 22 +++++++++++++++------- .generator/src/generator/setup.py | 3 ++- .generator/src/generator/utils.py | 5 +++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.generator/src/generator/formatter.py b/.generator/src/generator/formatter.py index ca3bcb435..18db24214 100644 --- a/.generator/src/generator/formatter.py +++ b/.generator/src/generator/formatter.py @@ -142,18 +142,26 @@ def get_terraform_schema_type(schema): }[schema.get("type")] -def date_time_formatter(name: str, schema: dict) -> str: +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 "date-time" format of the OpenAPI schema. - Go's time.Time type is used to represent date-time values and should be instead transformed into a string. + 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. """ - - if schema.get("format") == "date-time": - return f"{variable_name(name)}.String()" - return f"*{variable_name(name)}" + 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)}" diff --git a/.generator/src/generator/setup.py b/.generator/src/generator/setup.py index ae4ae3a99..24031fa79 100644 --- a/.generator/src/generator/setup.py +++ b/.generator/src/generator/setup.py @@ -21,12 +21,13 @@ def load_environment(version: str) -> Environment: 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.date_time_formatter + 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["print"] = utils.print_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 diff --git a/.generator/src/generator/utils.py b/.generator/src/generator/utils.py index 3b62661ab..6cacfb84c 100644 --- a/.generator/src/generator/utils.py +++ b/.generator/src/generator/utils.py @@ -71,3 +71,8 @@ def is_enum(schema): def is_nullable(schema): return schema.get("nullable", False) + + +def print_filter(value): + print(value) + return value From 5f2542d9ed9371d556a74c026c4bdafd348a39c5 Mon Sep 17 00:00:00 2001 From: Thibault Viennot Date: Wed, 26 Feb 2025 10:38:53 +0100 Subject: [PATCH 5/5] [Generator] (tidy) renamed filter --- .generator/src/generator/setup.py | 2 +- .generator/src/generator/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.generator/src/generator/setup.py b/.generator/src/generator/setup.py index 24031fa79..188af812c 100644 --- a/.generator/src/generator/setup.py +++ b/.generator/src/generator/setup.py @@ -27,7 +27,7 @@ def load_environment(version: str) -> Environment: env.filters["is_json_api"] = openapi.is_json_api env.filters["capitalize"] = utils.capitalize env.filters["is_primitive"] = utils.is_primitive - env.filters["print"] = utils.print_filter + 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 diff --git a/.generator/src/generator/utils.py b/.generator/src/generator/utils.py index 6cacfb84c..7e51bd4c6 100644 --- a/.generator/src/generator/utils.py +++ b/.generator/src/generator/utils.py @@ -73,6 +73,6 @@ def is_nullable(schema): return schema.get("nullable", False) -def print_filter(value): +def debug_filter(value): print(value) return value