From f76d02e4d20a2f751b54aaded92c4902d6d095c6 Mon Sep 17 00:00:00 2001 From: Ruben Hoenle Date: Wed, 7 Jan 2026 18:01:29 +0100 Subject: [PATCH 1/4] feat(golang): implement multi-version support relates to STACKITSDK-294 and STACKITSDK-297 --- languages/golang/.openapi-generator-ignore | 5 + languages/golang/blocklist.txt | 3 + .../compat-layer/.openapi-generator-ignore | 3 +- languages/golang/compat-layer/allow-list.txt | 36 + .../compat-layer/templates/api.mustache | 27 +- .../compat-layer/templates/client.mustache | 9 +- .../templates/configuration.mustache | 4 +- .../compat-layer/templates/model.mustache | 1 + .../templates/model_anyof.mustache | 3 + .../templates/model_enum.mustache | 15 + .../templates/model_oneof.mustache | 5 + .../templates/model_simple.mustache | 150 +++- .../templates/nullable_model.mustache | 8 + .../compat-layer/templates/response.mustache | 10 + .../compat-layer/templates/signing.mustache | 23 + .../compat-layer/templates/utils.mustache | 83 +- languages/golang/openapi-generator-config.yml | 11 + languages/golang/templates/client.mustache | 796 ++++++++++++++++++ .../golang/templates/configuration.mustache | 94 +++ .../golang/templates/custom/api_mock.mustache | 47 ++ scripts/generate-sdk/generate-sdk.sh | 2 +- scripts/generate-sdk/languages/go.sh | 123 ++- scripts/generate-sdk/languages/java.sh | 3 + scripts/generate-sdk/languages/python.sh | 3 + 24 files changed, 1405 insertions(+), 59 deletions(-) create mode 100644 languages/golang/.openapi-generator-ignore create mode 100644 languages/golang/compat-layer/allow-list.txt create mode 100644 languages/golang/openapi-generator-config.yml create mode 100644 languages/golang/templates/client.mustache create mode 100644 languages/golang/templates/configuration.mustache create mode 100644 languages/golang/templates/custom/api_mock.mustache diff --git a/languages/golang/.openapi-generator-ignore b/languages/golang/.openapi-generator-ignore new file mode 100644 index 0000000..617db47 --- /dev/null +++ b/languages/golang/.openapi-generator-ignore @@ -0,0 +1,5 @@ +README.md +git_push.sh +.travis.yml +.gitignore +api/openapi.yaml diff --git a/languages/golang/blocklist.txt b/languages/golang/blocklist.txt index fd7a510..33e90f0 100644 --- a/languages/golang/blocklist.txt +++ b/languages/golang/blocklist.txt @@ -10,3 +10,6 @@ pim smokeapi stackitmarketplace support +# CDN beta API versions currently have enums incorrectly defined in the OpenAPI spec +cdn-v1beta +cdn-v1beta2 diff --git a/languages/golang/compat-layer/.openapi-generator-ignore b/languages/golang/compat-layer/.openapi-generator-ignore index a1491ee..550ec0f 100644 --- a/languages/golang/compat-layer/.openapi-generator-ignore +++ b/languages/golang/compat-layer/.openapi-generator-ignore @@ -1,7 +1,6 @@ git_push.sh .travis.yml .gitignore -#utils.go README.md response.go api/openapi.yaml @@ -12,4 +11,4 @@ setup.py test-requirements.txt requirements.txt tox.ini -*/.github/* \ No newline at end of file +*/.github/* diff --git a/languages/golang/compat-layer/allow-list.txt b/languages/golang/compat-layer/allow-list.txt new file mode 100644 index 0000000..9de6775 --- /dev/null +++ b/languages/golang/compat-layer/allow-list.txt @@ -0,0 +1,36 @@ +# Transitional file to enable compatibility layer generation for selected services. +# Note: It shouldn't be needed to add any services here! +alb +auditlog +authorization +cdn +certificates +dns +edge +git +iaas +intake +kms +loadbalancer +logme +logs +mariadb +modelserving +mongodbflex +objectstorage +observability +opensearch +postgresflex +rabbitmq +redis +resourcemanager +runcommand +scf +secretsmanager +serverbackup +serverupdate +serviceaccount +serviceenablement +sfs +ske +sqlserverflex diff --git a/languages/golang/compat-layer/templates/api.mustache b/languages/golang/compat-layer/templates/api.mustache index e536fad..711091f 100644 --- a/languages/golang/compat-layer/templates/api.mustache +++ b/languages/golang/compat-layer/templates/api.mustache @@ -1,4 +1,5 @@ {{>partial_header}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead package {{packageName}} {{#operations}} @@ -16,6 +17,7 @@ import ( {{#generateInterfaces}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}} interface { {{#operation}} /* @@ -36,24 +38,21 @@ type {{classname}} interface { @param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}} @return {{{.}}}{{/returnType}} -{{#isDeprecated}} -Deprecated: {{{unescapedNotes}}} -{{/isDeprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead */ {{nickname}}Execute(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}} error) {{/operation}} } {{#operation}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request interface { {{#allParams}} {{^isPathParam}} {{#description}} // {{.}} {{/description}} -{{#isDeprecated}} -// Deprecated -{{/isDeprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead {{vendorExtensions.x-export-param-name}}({{paramName}} {{{dataType}}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request {{/isPathParam}} {{/allParams}} @@ -64,9 +63,11 @@ type {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/stru {{/generateInterfaces}} // {{classname}}Service {{classname}} service +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}Service service {{#operation}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{#structPrefix}}{{&classname}}{{/structPrefix}}{{operationId}}Request struct { ctx context.Context apiService *{{classname}}Service @@ -80,10 +81,7 @@ type {{#structPrefix}}{{&classname}}{{/structPrefix}}{{operationId}}Request stru {{#description}} // {{.}} {{/description}} -{{#isDeprecated}} -// Deprecated -{{/isDeprecated}} - +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{operationId}}Request) {{vendorExtensions.x-export-param-name}}({{paramName}} {{{dataType}}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request { r.{{paramName}} = {{^isFile}}&{{/isFile}}{{paramName}} return r @@ -92,6 +90,7 @@ func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{operationId}}Request) {{/isPathParam}} {{/allParams}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{operationId}}Request) Execute() ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}} error) { var ( localVarHTTPMethod = http.Method{{httpMethod}} @@ -412,8 +411,8 @@ func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{operationId}}Request) {{operationId}}: {{{summary}}}{{^summary}}Method for {{operationId}}{{/summary}} {{#notes}} -{{#isDeprecated}}Deprecated: {{/isDeprecated}}{{{unescapedNotes}}} {{/notes}} +Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}} @param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}} @@ -429,11 +428,7 @@ func (a *APIClient) {{{nickname}}}(ctx context.Context{{#pathParams}}, {{paramNa } } -{{#isDeprecated}} -/* -Deprecated: {{{unescapedNotes}}} -*/ -{{/isDeprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (a *APIClient) {{{nickname}}}Execute(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}} error){ r := {{#structPrefix}}{{&classname}}{{/structPrefix}}{{operationId}}Request{ apiService: a.defaultApi, diff --git a/languages/golang/compat-layer/templates/client.mustache b/languages/golang/compat-layer/templates/client.mustache index 4e38659..66040cc 100644 --- a/languages/golang/compat-layer/templates/client.mustache +++ b/languages/golang/compat-layer/templates/client.mustache @@ -1,4 +1,5 @@ {{>partial_header}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead package {{packageName}} import ( @@ -38,18 +39,21 @@ var ( // APIClient manages communication with the {{appName}} API v{{version}} // In most cases there should be only one, shared, APIClient. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type APIClient struct { cfg *config.Configuration common service // Reuse a single struct instead of allocating one for each service on the heap. defaultApi *DefaultApiService } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type service struct { client DefaultApi } // NewAPIClient creates a new API client. // Optionally receives configuration options +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewAPIClient(opts ...config.ConfigurationOption) (*APIClient, error) { cfg := NewConfiguration() @@ -146,6 +150,7 @@ func typeCheckParameter(obj interface{}, expected string, name string) error { return nil } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func ParameterValueToString( obj interface{}, key string ) string { if reflect.TypeOf(obj).Kind() != reflect.Ptr { return fmt.Sprintf("%v", obj) @@ -284,6 +289,7 @@ func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) { // Allow modification of underlying config for alternate implementations and testing // Caution: modifying the configuration while live can cause data races and potentially unwanted behavior +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (c *APIClient) GetConfig() *config.Configuration { return c.cfg } @@ -640,6 +646,7 @@ func parseCacheControl(headers http.Header) cacheControl { } // CacheExpires helper function to determine remaining time before repeating a request. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func CacheExpires(r *http.Response) time.Time { // Figure out when the cache expires. var expires time.Time @@ -670,4 +677,4 @@ func CacheExpires(r *http.Response) time.Time { func strlen(s string) int { return utf8.RuneCountInString(s) -} \ No newline at end of file +} diff --git a/languages/golang/compat-layer/templates/configuration.mustache b/languages/golang/compat-layer/templates/configuration.mustache index 50f1c33..17ff908 100644 --- a/languages/golang/compat-layer/templates/configuration.mustache +++ b/languages/golang/compat-layer/templates/configuration.mustache @@ -1,4 +1,5 @@ {{>partial_header}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead package {{packageName}} import ( @@ -6,6 +7,7 @@ import ( ) // NewConfiguration returns a new Configuration object +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewConfiguration() *config.Configuration { cfg := &config.Configuration{ DefaultHeader: make(map[string]string), @@ -89,4 +91,4 @@ func NewConfiguration() *config.Configuration { {{/apiInfo}} } return cfg -} \ No newline at end of file +} diff --git a/languages/golang/compat-layer/templates/model.mustache b/languages/golang/compat-layer/templates/model.mustache index 684af1d..4e02b75 100644 --- a/languages/golang/compat-layer/templates/model.mustache +++ b/languages/golang/compat-layer/templates/model.mustache @@ -1,4 +1,5 @@ {{>partial_header}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead package {{packageName}} {{#models}} diff --git a/languages/golang/compat-layer/templates/model_anyof.mustache b/languages/golang/compat-layer/templates/model_anyof.mustache index 3b221d8..238a9f8 100644 --- a/languages/golang/compat-layer/templates/model_anyof.mustache +++ b/languages/golang/compat-layer/templates/model_anyof.mustache @@ -1,4 +1,5 @@ // {{classname}} {{{description}}}{{^description}}struct for {{{classname}}}{{/description}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}} struct { {{#anyOf}} {{{.}}} *{{{.}}} @@ -6,6 +7,7 @@ type {{classname}} struct { } // Unmarshal JSON data into any of the pointers in the struct +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (dst *{{classname}}) UnmarshalJSON(data []byte) error { var err error {{#isNullable}} @@ -63,6 +65,7 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error { } // Marshal data from the first non-nil pointers in the struct to JSON +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (src *{{classname}}) MarshalJSON() ([]byte, error) { {{#anyOf}} if src.{{{.}}} != nil { diff --git a/languages/golang/compat-layer/templates/model_enum.mustache b/languages/golang/compat-layer/templates/model_enum.mustache index a5c8f93..8bdc277 100644 --- a/languages/golang/compat-layer/templates/model_enum.mustache +++ b/languages/golang/compat-layer/templates/model_enum.mustache @@ -1,4 +1,5 @@ // {{{classname}}} {{{description}}}{{^description}}the model '{{{classname}}}'{{/description}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{{classname}}} {{dataType}} // List of {{{name}}} @@ -7,12 +8,14 @@ const ( {{#enumVars}} {{^-first}} {{/-first}} + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead {{{classname.toUpperCase}}}_{{name}} {{{classname}}} = {{{value}}} {{/enumVars}} {{/allowableValues}} ) // All allowed values of {{{classname}}} enum +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead var Allowed{{{classname}}}EnumValues = []{{{classname}}}{ {{#allowableValues}} {{#enumVars}} @@ -21,6 +24,7 @@ var Allowed{{{classname}}}EnumValues = []{{{classname}}}{ {{/allowableValues}} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *{{{classname}}}) UnmarshalJSON(src []byte) error { var value {{dataType}} err := json.Unmarshal(src, &value) @@ -45,6 +49,7 @@ func (v *{{{classname}}}) UnmarshalJSON(src []byte) error { // New{{{classname}}}FromValue returns a pointer to a valid {{{classname}}} // for the value passed as argument, or an error if the value passed is not allowed by the enum +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func New{{{classname}}}FromValue(v {{dataType}}) (*{{{classname}}}, error) { ev := {{{classname}}}(v) if ev.IsValid() { @@ -55,6 +60,7 @@ func New{{{classname}}}FromValue(v {{dataType}}) (*{{{classname}}}, error) { } // IsValid return true if the value is valid for the enum, false otherwise +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v {{{classname}}}) IsValid() bool { for _, existing := range Allowed{{{classname}}}EnumValues { if existing == v { @@ -65,41 +71,50 @@ func (v {{{classname}}}) IsValid() bool { } // Ptr returns reference to {{{name}}} value +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v {{{classname}}}) Ptr() *{{{classname}}} { return &v } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type Nullable{{{classname}}} struct { value *{{{classname}}} isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{classname}}) Get() *{{classname}} { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{classname}}) Set(val *{{classname}}) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{classname}}) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{classname}}) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullable{{classname}}(val *{{classname}}) *Nullable{{classname}} { return &Nullable{{classname}}{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{{classname}}}) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{{classname}}}) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) diff --git a/languages/golang/compat-layer/templates/model_oneof.mustache b/languages/golang/compat-layer/templates/model_oneof.mustache index f179d14..7dadc07 100644 --- a/languages/golang/compat-layer/templates/model_oneof.mustache +++ b/languages/golang/compat-layer/templates/model_oneof.mustache @@ -1,4 +1,5 @@ // {{classname}} - {{{description}}}{{^description}}struct for {{{classname}}}{{/description}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}} struct { {{#oneOf}} {{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} *{{{.}}} @@ -7,6 +8,7 @@ type {{classname}} struct { {{#oneOf}} // {{{.}}}As{{classname}} is a convenience function that returns {{{.}}} wrapped in {{classname}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func {{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}As{{classname}}(v *{{{.}}}) {{classname}} { return {{classname}}{ {{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}: v, @@ -16,6 +18,7 @@ func {{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}As{{classname}}(v *{ {{/oneOf}} // Unmarshal JSON data into one of the pointers in the struct +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (dst *{{classname}}) UnmarshalJSON(data []byte) error { var err error {{#isNullable}} @@ -130,6 +133,7 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error { // Marshal data from the first non-nil pointers in the struct to JSON func (src {{classname}}) MarshalJSON() ([]byte, error) { +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead {{#oneOf}} if src.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} != nil { return json.Marshal(&src.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}}) @@ -140,6 +144,7 @@ func (src {{classname}}) MarshalJSON() ([]byte, error) { } // Get the actual instance +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (obj *{{classname}}) GetActualInstance() (interface{}) { if obj == nil { return nil diff --git a/languages/golang/compat-layer/templates/model_simple.mustache b/languages/golang/compat-layer/templates/model_simple.mustache index 8abbfc6..b4b570f 100644 --- a/languages/golang/compat-layer/templates/model_simple.mustache +++ b/languages/golang/compat-layer/templates/model_simple.mustache @@ -29,9 +29,13 @@ var _ MappedNullable = &{{classname}}{} {{^isEnum}} {{#isNumber}} // isNumber +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -44,15 +48,20 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } {{/isNumber}} {{#isFloat}} // isFloat +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -65,15 +74,20 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } {{/isFloat}} {{#isDouble}} // isDouble +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}float64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -86,6 +100,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -94,9 +109,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{! isShort and isInteger may be true at the same time, so select one}} {{^isInteger}} // isShort +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -109,6 +128,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -116,9 +136,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{/isShort}} {{#isInteger}} // isInteger +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -131,15 +155,20 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } {{/isInteger}} {{#isLong}} // isLong +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}int64 +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -152,6 +181,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -163,7 +193,9 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{#isNullable}} {{! nullable strings have a special type}} // isNullableString +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *NullableString +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -176,6 +208,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return arg.Get(),true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { if IsNil(*arg) { *arg = NewNullableString(val) @@ -187,7 +220,9 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{^isNullable}} {{! non nullable strings are plain string pointers}} // isNotNullableString +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *string +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -200,19 +235,26 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } {{/isNullable}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}string +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}string {{/isArray}} {{/isString}} {{#isAnyType}} // isAny +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = any +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = any +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = any +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -225,6 +267,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -234,9 +277,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{#isDateTime}} {{! special handling for date-time}} // isDateTime +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *time.Time +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}time.Time +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}time.Time +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -249,6 +296,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -256,9 +304,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{#isDate}} {{! special handling for date}} // isDate +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *string +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}string +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}string +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -271,6 +323,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -282,6 +335,7 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu // {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} {{{description}}}{{^description}}the model '{{{classname}}}'{{/description}} // value type for enums +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} {{#isNumeric}}int{{/isNumeric}}{{^isNumeric}}string{{/isNumeric}} // List of {{name}} @@ -290,12 +344,14 @@ const ( {{#enumVars}} {{^-first}} {{/-first}} + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead {{{classname.toUpperCase}}}{{{enumName}}}_{{name}} {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} = {{{value}}} {{/enumVars}} {{/allowableValues}} ) // All allowed values of {{{classname}}} enum +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead var Allowed{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}EnumValues = []{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}{ {{#allowableValues}} {{#enumVars}} @@ -304,6 +360,7 @@ var Allowed{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titl {{/allowableValues}} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) UnmarshalJSON(src []byte) error { // use a type alias to prevent infinite recursion during unmarshal, // see https://biscuit.ninja/posts/go-avoid-an-infitine-loop-with-custom-json-unmarshallers @@ -331,6 +388,7 @@ func (v *{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlec // New{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}FromValue returns a pointer to a valid {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} // for the value passed as argument, or an error if the value passed is not allowed by the enum +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func New{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}FromValue(v {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) (*{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}, error) { ev := {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}(v) if ev.IsValid() { @@ -341,6 +399,7 @@ func New{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titleca } // IsValid return true if the value is valid for the enum, false otherwise +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) IsValid() bool { for _, existing := range Allowed{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}EnumValues { if existing == v { @@ -351,49 +410,62 @@ func (v {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titleca } // Ptr returns reference to {{{name}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} value +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v {{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) Ptr() *{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} { return &v } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type Nullable{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} struct { value *{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) Get() *{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) Set(val *{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullable{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}(val *{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) *Nullable{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} { return &Nullable{{classname}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}}) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}{{{classname}}}{{#lambda.titlecase}}{{nameInCamelCase}}{{/lambda.titlecase}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -406,15 +478,20 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } {{/isEnum}} {{^isEnum}} // isEnumRef +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *{{^isNumeric}}{{dataType}}{{/isNumeric}}{{#isNumeric}}int64{{/isNumeric}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}{{^isNumeric}}{{dataType}}{{/isNumeric}}{{#isNumeric}}int64{{/isNumeric}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}{{^isNumeric}}{{dataType}}{{/isNumeric}}{{#isNumeric}}int64{{/isNumeric}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -427,6 +504,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -435,9 +513,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{#isModel}} {{! special handling for recursive datatypes}} // isModel +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -450,6 +532,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -462,9 +545,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{^isEnumRef}} // fallback {{! everything else will end up here}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -477,6 +564,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -488,9 +576,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{/isPrimitiveType}} {{#isArray}} // isArray +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -503,6 +595,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -511,9 +604,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{#isFreeFormObject}} // isFreeform +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -526,6 +623,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -534,9 +632,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{^isFreeFormObject}} {{^isArray}} // isContainer +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}{{dataType}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -549,6 +651,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -557,9 +660,13 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{/isContainer}} {{#isByteArray}} // isByteArray +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *[]byte +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}[]byte +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}[]byte +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -572,15 +679,20 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } {{/isByteArray}} {{#isBoolean}} // isBoolean +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}AttributeType = *bool +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}ArgType = {{#isNullable}}*{{/isNullable}}bool +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}}{{getter}}RetType = {{#isNullable}}*{{/isNullable}}bool +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}AttributeType) (ret {{classname}}{{getter}}RetType, ok bool) { if arg == nil { {{#isNullable}} @@ -593,6 +705,7 @@ func get{{classname}}{{getter}}AttributeTypeOk(arg {{classname}}{{getter}}Attrib return {{^isNullable}}*{{/isNullable}}arg,true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}AttributeType, val {{classname}}{{getter}}RetType) { *arg={{^isNullable}}&{{/isNullable}}val } @@ -601,6 +714,7 @@ func set{{classname}}{{getter}}AttributeType(arg *{{classname}}{{getter}}Attribu {{/vars}} // {{classname}} {{{description}}}{{^description}}struct for {{{classname}}}{{/description}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type {{classname}} struct { {{#parent}} {{^isMap}} @@ -645,11 +759,13 @@ type {{classname}} struct { {{#isAdditionalPropertiesTrue}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type _{{{classname}}} {{{classname}}} {{/isAdditionalPropertiesTrue}} {{^isAdditionalPropertiesTrue}} {{#hasRequired}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type _{{{classname}}} {{{classname}}} {{/hasRequired}} @@ -658,6 +774,7 @@ type _{{{classname}}} {{{classname}}} // This constructor will assign default values to properties that have it defined, // and makes sure properties required by API are set, but the set of arguments // will change when the set of required properties is changed +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func New{{classname}}({{#requiredVars}}{{nameInCamelCase}} {{classname}}{{getter}}ArgType{{^-last}}, {{/-last}}{{/requiredVars}}) *{{classname}} { this := {{classname}}{} {{#allVars}} @@ -671,6 +788,7 @@ func New{{classname}}({{#requiredVars}}{{nameInCamelCase}} {{classname}}{{getter // New{{classname}}WithDefaults instantiates a new {{classname}} object // This constructor will only assign default values to properties that have it defined, // but it doesn't guarantee that properties required by API are set +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func New{{classname}}WithDefaults() *{{classname}} { this := {{classname}}{} {{#vars}} @@ -703,9 +821,7 @@ func New{{classname}}WithDefaults() *{{classname}} { {{#isNullable}} // If the value is explicit nil, the zero value for {{vendorExtensions.x-go-base-type}} will be returned {{/isNullable}} -{{#deprecated}} -// Deprecated -{{/deprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Get{{name}}() (ret {{classname}}{{getter}}RetType) { ret,_ = o.Get{{name}}Ok() return ret @@ -716,17 +832,13 @@ func (o *{{classname}}) Get{{name}}() (ret {{classname}}{{getter}}RetType) { {{#isNullable}} // NOTE: If the value is an explicit nil, `nil, true` will be returned {{/isNullable}} -{{#deprecated}} -// Deprecated -{{/deprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Get{{name}}Ok() (ret {{classname}}{{getter}}RetType, ok bool) { return get{{classname}}{{getter}}AttributeTypeOk(o.{{name}}) } // Set{{name}} sets field value -{{#deprecated}} -// Deprecated -{{/deprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Set{{name}}(v {{classname}}{{getter}}RetType) { set{{classname}}{{getter}}AttributeType(&o.{{name}},v) } @@ -734,9 +846,7 @@ func (o *{{classname}}) Set{{name}}(v {{classname}}{{getter}}RetType) { {{/required}} {{^required}} // Get{{name}} returns the {{name}} field value if set, zero value otherwise{{#isNullable}} (both if not set or set to explicit null){{/isNullable}}. -{{#deprecated}} -// Deprecated -{{/deprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Get{{name}}() (res {{classname}}{{getter}}RetType) { res,_ = o.Get{{name}}Ok() return @@ -747,23 +857,20 @@ func (o *{{classname}}) Get{{name}}() (res {{classname}}{{getter}}RetType) { {{#isNullable}} // NOTE: If the value is an explicit nil, `nil, true` will be returned {{/isNullable}} -{{#deprecated}} -// Deprecated -{{/deprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Get{{name}}Ok() (ret {{classname}}{{getter}}RetType, ok bool) { return get{{classname}}{{getter}}AttributeTypeOk(o.{{name}}) } // Has{{name}} returns a boolean if a field has been set. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Has{{name}}() bool { _,ok:=o.Get{{name}}Ok() return ok } // Set{{name}} gets a reference to the given {{#isNumber}}float64{{/isNumber}}{{#isFloat}}float64{{/isFloat}}{{#isDouble}}float64{{/isDouble}}{{#isInteger}}int64{{/isInteger}}{{#isLong}}int64{{/isLong}}{{^isNumeric}}{{vendorExtensions.x-go-base-type}}{{/isNumeric}} and assigns it to the {{name}} field. -{{#deprecated}} -// Deprecated -{{/deprecated}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Set{{name}}(v {{classname}}{{getter}}RetType) { set{{classname}}{{getter}}AttributeType(&o.{{name}},v) } @@ -772,11 +879,13 @@ func (o *{{classname}}) Set{{name}}(v {{classname}}{{getter}}RetType) { {{#isNullable}} {{^vendorExtensions.x-golang-is-container}} // Set{{name}}Nil sets the value for {{name}} to be an explicit nil +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Set{{name}}Nil() { o.{{name}} = nil } // Unset{{name}} ensures that no value is present for {{name}}, not even an explicit nil +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{classname}}) Unset{{name}}() { o.{{name}} = nil } @@ -786,6 +895,7 @@ func (o *{{classname}}) Unset{{name}}() { {{/required}} {{/vars}} {{#vendorExtensions.x-go-generate-marshal-json}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o {{classname}}) MarshalJSON() ([]byte, error) { toSerialize,err := o.ToMap() if err != nil { @@ -795,6 +905,7 @@ func (o {{classname}}) MarshalJSON() ([]byte, error) { } {{/vendorExtensions.x-go-generate-marshal-json}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o {{classname}}) ToMap() (map[string]interface{}, error) { toSerialize := {{#isArray}}make([]interface{}, len(o.Items)){{/isArray}}{{^isArray}}map[string]interface{}{}{{/isArray}} {{#parent}} @@ -835,10 +946,12 @@ func (o {{classname}}) ToMap() (map[string]interface{}, error) { {{#vendorExtensions.x-go-generate-unmarshal-json}} {{#isAdditionalPropertiesTrue}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) { {{/isAdditionalPropertiesTrue}} {{^isAdditionalPropertiesTrue}} {{#hasRequired}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) { {{/hasRequired}} {{/isAdditionalPropertiesTrue}} @@ -1006,6 +1119,7 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) { {{/hasRequired}} {{/isAdditionalPropertiesTrue}} {{#isArray}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) { return json.Unmarshal(data, &o.Items) } diff --git a/languages/golang/compat-layer/templates/nullable_model.mustache b/languages/golang/compat-layer/templates/nullable_model.mustache index 7b60ce6..06ada56 100644 --- a/languages/golang/compat-layer/templates/nullable_model.mustache +++ b/languages/golang/compat-layer/templates/nullable_model.mustache @@ -1,34 +1,42 @@ +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type Nullable{{{classname}}} struct { value {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{{classname}}} isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{classname}}) Get() {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{classname}} { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{classname}}) Set(val {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{classname}}) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{classname}}) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{classname}}) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullable{{classname}}(val {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{classname}}) *Nullable{{classname}} { return &Nullable{{classname}}{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v Nullable{{{classname}}}) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *Nullable{{{classname}}}) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) diff --git a/languages/golang/compat-layer/templates/response.mustache b/languages/golang/compat-layer/templates/response.mustache index 4691e8f..1ad3dbf 100644 --- a/languages/golang/compat-layer/templates/response.mustache +++ b/languages/golang/compat-layer/templates/response.mustache @@ -1,4 +1,5 @@ {{>partial_header}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead package {{packageName}} import ( @@ -6,24 +7,32 @@ import ( ) // APIResponse stores the API response returned by the server. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type APIResponse struct { + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead *http.Response `json:"-"` + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead Message string `json:"message,omitempty"` // Operation is the name of the OpenAPI operation. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead Operation string `json:"operation,omitempty"` // RequestURL is the request URL. This value is always available, even if the // embedded *http.Response is nil. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead RequestURL string `json:"url,omitempty"` // Method is the HTTP method used for the request. This value is always // available, even if the embedded *http.Response is nil. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead Method string `json:"method,omitempty"` // Payload holds the contents of the response body (which may be nil or empty). // This is provided here as the raw response.Body() reader will have already // been drained. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead Payload []byte `json:"-"` } // NewAPIResponse returns a new APIResponse object. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewAPIResponse(r *http.Response) *APIResponse { response := &APIResponse{Response: r} @@ -31,6 +40,7 @@ func NewAPIResponse(r *http.Response) *APIResponse { } // NewAPIResponseWithError returns a new APIResponse object with the provided error message. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewAPIResponseWithError(errorMessage string) *APIResponse { response := &APIResponse{Message: errorMessage} diff --git a/languages/golang/compat-layer/templates/signing.mustache b/languages/golang/compat-layer/templates/signing.mustache index a271fcf..553daf3 100644 --- a/languages/golang/compat-layer/templates/signing.mustache +++ b/languages/golang/compat-layer/templates/signing.mustache @@ -1,4 +1,5 @@ {{>partial_header}} +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead package {{packageName}} import ( @@ -25,24 +26,31 @@ const ( // Constants for HTTP signature parameters. // The '(request-target)' parameter concatenates the lowercased :method, an // ASCII space, and the :path pseudo-headers. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpSignatureParameterRequestTarget string = "(request-target)" // The '(created)' parameter expresses when the signature was // created. The value MUST be a Unix timestamp integer value. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpSignatureParameterCreated string = "(created)" // The '(expires)' parameter expresses when the signature ceases to // be valid. The value MUST be a Unix timestamp integer value. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpSignatureParameterExpires string = "(expires)" ) const ( // Constants for HTTP headers. // The 'Host' header, as defined in RFC 2616, section 14.23. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpHeaderHost string = "Host" // The 'Date' header. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpHeaderDate string = "Date" // The digest header, as defined in RFC 3230, section 4.3.2. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpHeaderDigest string = "Digest" // The HTTP Authorization header, as defined in RFC 7235, section 4.2. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpHeaderAuthorization string = "Authorization" ) @@ -52,28 +60,36 @@ const ( // RSASSA-PSS, and ECDSA. // The hash is SHA-512. // This is the default value. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpSigningSchemeHs2019 string = "hs2019" // Use RSASSA-PKCS1-v1_5 with SHA-512 hash. Deprecated. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpSigningSchemeRsaSha512 string = "rsa-sha512" // Use RSASSA-PKCS1-v1_5 with SHA-256 hash. Deprecated. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpSigningSchemeRsaSha256 string = "rsa-sha256" // RFC 8017 section 7.2 // Calculate the message signature using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. // PKCSV1_5 is deterministic. The same message and key will produce an identical // signature value each time. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpSigningAlgorithmRsaPKCS1v15 string = "RSASSA-PKCS1-v1_5" // Calculate the message signature using probabilistic signature scheme RSASSA-PSS. // PSS is randomized and will produce a different signature value each time. + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpSigningAlgorithmRsaPSS string = "RSASSA-PSS" // HashAlgorithm Sha256 for generating hash + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpHashAlgorithmSha256 string = "sha256" // HashAlgorithm Sha512 for generating hash + // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead HttpHashAlgorithmSha512 string = "sha512" ) +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead var supportedSigningSchemes = map[string]bool{ HttpSigningSchemeHs2019: true, HttpSigningSchemeRsaSha512: true, @@ -104,6 +120,7 @@ var supportedSigningSchemes = map[string]bool{ // 1. Calculate a digest of request body, as specified in RFC3230, section 4.3.2. // 2. Set the 'Digest' header in the request body. // 3. Include the 'Digest' header and value in the HTTP signature. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type HttpSignatureAuth struct { KeyId string // A key identifier. PrivateKeyPath string // The path to the private key. @@ -123,6 +140,7 @@ type HttpSignatureAuth struct { } // SetPrivateKey accepts a private key string and sets it. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (h *HttpSignatureAuth) SetPrivateKey(privateKey string) error { return h.parsePrivateKey([]byte(privateKey)) } @@ -130,6 +148,7 @@ func (h *HttpSignatureAuth) SetPrivateKey(privateKey string) error { // ContextWithValue validates the HttpSignatureAuth configuration parameters and returns a context // suitable for HTTP signature. An error is returned if the HttpSignatureAuth configuration parameters // are invalid. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (h *HttpSignatureAuth) ContextWithValue(ctx context.Context) (context.Context, error) { if h.KeyId == "" { return nil, fmt.Errorf("key ID must be specified") @@ -160,6 +179,7 @@ func (h *HttpSignatureAuth) ContextWithValue(ctx context.Context) (context.Conte } // GetPublicKey returns the public key associated with this HTTP signature configuration. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (h *HttpSignatureAuth) GetPublicKey() (crypto.PublicKey, error) { if h.privateKey == nil { if err := h.loadPrivateKey(); err != nil { @@ -180,6 +200,7 @@ func (h *HttpSignatureAuth) GetPublicKey() (crypto.PublicKey, error) { // loadPrivateKey reads the private key from the file specified in the HttpSignatureAuth. // The key is loaded only when privateKey is not already set. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (h *HttpSignatureAuth) loadPrivateKey() (err error) { if h.privateKey != nil { return nil @@ -201,6 +222,7 @@ func (h *HttpSignatureAuth) loadPrivateKey() (err error) { } // parsePrivateKey decodes privateKey byte array to crypto.PrivateKey type. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (h *HttpSignatureAuth) parsePrivateKey(priv []byte) error { pemBlock, _ := pem.Decode(priv) if pemBlock == nil { @@ -248,6 +270,7 @@ func (h *HttpSignatureAuth) parsePrivateKey(priv []byte) error { // concatenated, separated by a ASCII comma and an ASCII space // ', ', and used in the order in which they will appear in the // transmitted HTTP message. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func SignRequest( ctx context.Context, r *http.Request, diff --git a/languages/golang/compat-layer/templates/utils.mustache b/languages/golang/compat-layer/templates/utils.mustache index 6b84931..254911e 100644 --- a/languages/golang/compat-layer/templates/utils.mustache +++ b/languages/golang/compat-layer/templates/utils.mustache @@ -8,341 +8,419 @@ import ( ) // PtrBool is a helper routine that returns a pointer to given boolean value. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func PtrBool(v bool) *bool { return &v } // PtrInt is a helper routine that returns a pointer to given integer value. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func PtrInt(v int) *int { return &v } // PtrInt32 is a helper routine that returns a pointer to given integer value. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func PtrInt32(v int32) *int32 { return &v } // PtrInt64 is a helper routine that returns a pointer to given integer value. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func PtrInt64(v int64) *int64 { return &v } // PtrFloat32 is a helper routine that returns a pointer to given float value. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func PtrFloat32(v float32) *float32 { return &v } // PtrFloat64 is a helper routine that returns a pointer to given float value. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func PtrFloat64(v float64) *float64 { return &v } // PtrString is a helper routine that returns a pointer to given string value. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func PtrString(v string) *string { return &v } // PtrTime is helper routine that returns a pointer to given Time value. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func PtrTime(v time.Time) *time.Time { return &v } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableValue[T any] struct { value *T isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableValue[T]) Get() *T { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableValue[T]) Set(val *T) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableValue[T]) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableValue[T]) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableBool struct { value *bool isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableBool) Get() *bool { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableBool) Set(val *bool) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableBool) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableBool) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullableBool(val *bool) *NullableBool { return &NullableBool{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableBool) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableBool) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableInt struct { value *int isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt) Get() *int { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt) Set(val *int) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullableInt(val *int) *NullableInt { return &NullableInt{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableInt32 struct { value *int32 isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt32) Get() *int32 { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt32) Set(val *int32) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt32) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt32) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullableInt32(val *int32) *NullableInt32 { return &NullableInt32{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt32) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt32) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableInt64 struct { value *int64 isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt64) Get() *int64 { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt64) Set(val *int64) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt64) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt64) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullableInt64(val *int64) *NullableInt64 { return &NullableInt64{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableInt64) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableInt64) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableFloat32 struct { value *float32 isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableFloat32) Get() *float32 { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableFloat32) Set(val *float32) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableFloat32) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableFloat32) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullableFloat32(val *float32) *NullableFloat32 { return &NullableFloat32{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableFloat32) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableFloat32) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableFloat64 struct { value *float64 isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableFloat64) Get() *float64 { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableFloat64) Set(val *float64) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableFloat64) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableFloat64) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullableFloat64(val *float64) *NullableFloat64 { return &NullableFloat64{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableFloat64) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableFloat64) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableString struct { value *string isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableString) Get() *string { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableString) Set(val *string) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableString) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableString) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullableString(val *string) *NullableString { return &NullableString{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableString) MarshalJSON() ([]byte, error) { return json.Marshal(v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableString) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type NullableTime struct { value *time.Time isSet bool } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableTime) Get() *time.Time { return v.value } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableTime) Set(val *time.Time) { v.value = val v.isSet = true } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableTime) IsSet() bool { return v.isSet } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableTime) Unset() { v.value = nil v.isSet = false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func NewNullableTime(val *time.Time) *NullableTime { return &NullableTime{value: val, isSet: true} } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v NullableTime) MarshalJSON() ([]byte, error) { return v.value.MarshalJSON() } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func (v *NullableTime) UnmarshalJSON(src []byte) error { v.isSet = true return json.Unmarshal(src, &v.value) } // IsNil checks if an input is nil +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func IsNil(i interface{}) bool { if i == nil { return true @@ -359,17 +437,20 @@ func IsNil(i interface{}) bool { return false } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead type MappedNullable interface { ToMap() (map[string]interface{}, error) } +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead const letterRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // randString returns a random string with a specified length. It panics if n <= 0. +// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func randString(n int) string { b := make([]byte, n) for i := range b { b[i] = letterRunes[rand.Intn(len(letterRunes))] } return string(b) -} \ No newline at end of file +} diff --git a/languages/golang/openapi-generator-config.yml b/languages/golang/openapi-generator-config.yml new file mode 100644 index 0000000..3ea4d2e --- /dev/null +++ b/languages/golang/openapi-generator-config.yml @@ -0,0 +1,11 @@ +useOneOfDiscriminatorLookup: true +additionalProperties: + withGoMod: false + isGoSubmodule: true + enumClassPrefix: true + generateInterfaces: true +templateDir: languages/golang/templates +files: + custom/api_mock.mustache: + templateType: API + destinationFilename: _mock.go diff --git a/languages/golang/templates/client.mustache b/languages/golang/templates/client.mustache new file mode 100644 index 0000000..c9ed660 --- /dev/null +++ b/languages/golang/templates/client.mustache @@ -0,0 +1,796 @@ +{{! This template was customized to support the custom configuration options from the core module. See https://github.com/OpenAPITools/openapi-generator/blob/v7.20.0/modules/openapi-generator/src/main/resources/go/client.mustache for the original template }} +{{>partial_header}} +package {{packageName}} + +import ( + "bytes" + "context" + "encoding/json" + "encoding/xml" + "errors" + "fmt" + "io" + "log" + "mime/multipart" + "net/http" + "net/http/httputil" + "net/url" + "os" + "path/filepath" + "reflect" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" + + {{! TEMPLATE CUSTOMIZATION - BEGIN }} + "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/core/auth" + {{! TEMPLATE CUSTOMIZATION - END }} + + {{#hasOAuthMethods}} + "golang.org/x/oauth2" + {{/hasOAuthMethods}} + {{#withAWSV4Signature}} + awsv4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" + awscredentials "github.com/aws/aws-sdk-go-v2/credentials" + "crypto/sha256" + "encoding/hex" + {{/withAWSV4Signature}} +) + +var ( + JsonCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:[^;]+\+)?json)`) + XmlCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:[^;]+\+)?xml)`) + queryParamSplit = regexp.MustCompile(`(^|&)([^&]+)`) + queryDescape = strings.NewReplacer( "%5B", "[", "%5D", "]" ) +) + +// APIClient manages communication with the {{appName}} API v{{version}} +// In most cases there should be only one, shared, APIClient. +type APIClient struct { + {{! TEMPLATE CUSTOMIZATION - BEGIN - use the configuration type from the STACKIT SDK core module instead of the one provided by OpenAPI generator }} + cfg *config.Configuration + {{! TEMPLATE CUSTOMIZATION - END }} + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // API Services +{{#apiInfo}} +{{#apis}} +{{#operations}} + + {{classname}} {{#generateInterfaces}}{{classname}}{{/generateInterfaces}}{{^generateInterfaces}}*{{classname}}Service{{/generateInterfaces}} +{{/operations}} +{{/apis}} +{{/apiInfo}} +} + +type service struct { + client *APIClient +} + +// NewAPIClient creates a new API client. Requires a userAgent string describing your application. +// optionally a custom http.Client to allow for advanced features such as caching. +{{! TEMPLATE CUSTOMIZATION - BEGIN - use the configuration type from the STACKIT SDK core module instead of the one provided by OpenAPI generator }} +func NewAPIClient(opts ...config.ConfigurationOption) (*APIClient, error) { + cfg := NewConfiguration() + + for _, option := range opts { + err := option(cfg) + if err != nil { + return nil, fmt.Errorf("configuring the client: %w", err) + } + } + + err := config.ConfigureRegion(cfg) + if err != nil { + return nil, fmt.Errorf("configuring region: %w", err) + } + + if cfg.HTTPClient == nil { + cfg.HTTPClient = &http.Client{} + } + + authRoundTripper, err := auth.SetupAuth(cfg) + if err != nil { + return nil, fmt.Errorf("setting up authentication: %w", err) + } + + roundTripper := authRoundTripper + if cfg.Middleware != nil { + roundTripper = config.ChainMiddleware(roundTripper, cfg.Middleware...) + } + + cfg.HTTPClient.Transport = roundTripper +{{! TEMPLATE CUSTOMIZATION - END }} + + c := &APIClient{} + c.cfg = cfg + c.common.client = c + +{{#apiInfo}} + // API Services +{{#apis}} +{{#operations}} + c.{{classname}} = (*{{classname}}Service)(&c.common) +{{/operations}} +{{/apis}} +{{/apiInfo}} + + return c, nil +} + +func atoi(in string) (int, error) { + return strconv.Atoi(in) +} + +// selectHeaderContentType select a content type from the available list. +func selectHeaderContentType(contentTypes []string) string { + if len(contentTypes) == 0 { + return "" + } + if contains(contentTypes, "application/json") { + return "application/json" + } + return contentTypes[0] // use the first content type specified in 'consumes' +} + +// selectHeaderAccept join all accept types and return +func selectHeaderAccept(accepts []string) string { + if len(accepts) == 0 { + return "" + } + + if contains(accepts, "application/json") { + return "application/json" + } + + return strings.Join(accepts, ",") +} + +// contains is a case insensitive match, finding needle in a haystack +func contains(haystack []string, needle string) bool { + for _, a := range haystack { + if strings.EqualFold(a, needle) { + return true + } + } + return false +} + +// Verify optional parameters are of the correct type. +func typeCheckParameter(obj interface{}, expected string, name string) error { + // Make sure there is an object. + if obj == nil { + return nil + } + + // Check the type is as expected. + if reflect.TypeOf(obj).String() != expected { + return fmt.Errorf("expected %s to be of type %s but received %s", name, expected, reflect.TypeOf(obj).String()) + } + return nil +} + +func parameterValueToString( obj interface{}, key string ) string { + if reflect.TypeOf(obj).Kind() != reflect.Ptr { + if actualObj, ok := obj.(interface{ GetActualInstanceValue() interface{} }); ok { + return fmt.Sprintf("%v", actualObj.GetActualInstanceValue()) + } + + return fmt.Sprintf("%v", obj) + } + var param,ok = obj.(MappedNullable) + if !ok { + return "" + } + dataMap,err := param.ToMap() + if err != nil { + return "" + } + return fmt.Sprintf("%v", dataMap[key]) +} + +// parameterAddToHeaderOrQuery adds the provided object to the request header or url query +// supporting deep object syntax +func parameterAddToHeaderOrQuery(headerOrQueryParams interface{}, keyPrefix string, obj interface{}, style string, collectionType string) { + var v = reflect.ValueOf(obj) + var value = "" + if v == reflect.ValueOf(nil) { + value = "null" + } else { + switch v.Kind() { + case reflect.Invalid: + value = "invalid" + + case reflect.Struct: + if t,ok := obj.(MappedNullable); ok { + dataMap,err := t.ToMap() + if err != nil { + return + } + parameterAddToHeaderOrQuery(headerOrQueryParams, keyPrefix, dataMap, style, collectionType) + return + } + if t, ok := obj.(time.Time); ok { + parameterAddToHeaderOrQuery(headerOrQueryParams, keyPrefix, t.Format(time.RFC3339Nano), style, collectionType) + return + } + value = v.Type().String() + " value" + case reflect.Slice: + var indValue = reflect.ValueOf(obj) + if indValue == reflect.ValueOf(nil) { + return + } + var lenIndValue = indValue.Len() + for i:=0;i 0 || (len(formFiles) > 0) { + if body != nil { + return nil, errors.New("Cannot specify postBody and multipart form at the same time.") + } + body = &bytes.Buffer{} + w := multipart.NewWriter(body) + + for k, v := range formParams { + for _, iv := range v { + if strings.HasPrefix(k, "@") { // file + err = addFile(w, k[1:], iv) + if err != nil { + return nil, err + } + } else { // form value + w.WriteField(k, iv) + } + } + } + for _, formFile := range formFiles { + if len(formFile.fileBytes) > 0 && formFile.fileName != "" { + w.Boundary() + part, err := w.CreateFormFile(formFile.formFileName, filepath.Base(formFile.fileName)) + if err != nil { + return nil, err + } + _, err = part.Write(formFile.fileBytes) + if err != nil { + return nil, err + } + } + } + + // Set the Boundary in the Content-Type + headerParams["Content-Type"] = w.FormDataContentType() + + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + w.Close() + } + + if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 { + if body != nil { + return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.") + } + body = &bytes.Buffer{} + body.WriteString(formParams.Encode()) + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + } + + // Setup path and query parameters + url, err := url.Parse(path) + if err != nil { + return nil, err + } + + // Override request host, if applicable + if c.cfg.Host != "" { + url.Host = c.cfg.Host + } + + // Override request scheme, if applicable + if c.cfg.Scheme != "" { + url.Scheme = c.cfg.Scheme + } + + // Adding Query Param + query := url.Query() + for k, v := range queryParams { + for _, iv := range v { + query.Add(k, iv) + } + } + + // Encode the parameters. + url.RawQuery = queryParamSplit.ReplaceAllStringFunc(query.Encode(), func(s string) string { + pieces := strings.Split(s, "=") + pieces[0] = queryDescape.Replace(pieces[0]) + return strings.Join(pieces, "=") + }) + + // Generate a new request + if body != nil { + localVarRequest, err = http.NewRequest(method, url.String(), body) + } else { + localVarRequest, err = http.NewRequest(method, url.String(), nil) + } + if err != nil { + return nil, err + } + + // add header parameters, if any + if len(headerParams) > 0 { + headers := http.Header{} + for h, v := range headerParams { + headers[h] = []string{v} + } + localVarRequest.Header = headers + } + + // Add the user agent to the request. + localVarRequest.Header.Add("User-Agent", c.cfg.UserAgent) + + if ctx != nil { + // add context to the request + localVarRequest = localVarRequest.WithContext(ctx) + + // Walk through any authentication. + + {{#hasOAuthMethods}} + // OAuth2 authentication + if tok, ok := ctx.Value(ContextOAuth2).(oauth2.TokenSource); ok { + // We were able to grab an oauth2 token from the context + var latestToken *oauth2.Token + if latestToken, err = tok.Token(); err != nil { + return nil, err + } + + latestToken.SetAuthHeader(localVarRequest) + } + + {{/hasOAuthMethods}} + {{#hasHttpBasicMethods}} + // Basic HTTP Authentication + if auth, ok := ctx.Value(ContextBasicAuth).(BasicAuth); ok { + localVarRequest.SetBasicAuth(auth.UserName, auth.Password) + } + + {{/hasHttpBasicMethods}} + {{#hasHttpBearerMethods}} + // AccessToken Authentication + if auth, ok := ctx.Value(ContextAccessToken).(string); ok { + localVarRequest.Header.Add("Authorization", "Bearer "+auth) + } + + {{/hasHttpBearerMethods}} + {{#withAWSV4Signature}} + // AWS Signature v4 Authentication + if auth, ok := ctx.Value(ContextAWSv4).(AWSv4); ok { + credsProvider := awscredentials.NewStaticCredentialsProvider(auth.AccessKey, auth.SecretKey, auth.SessionToken) + creds, err := credsProvider.Retrieve(ctx) + if err != nil { + return nil, err + } + + // Define default values for region and service to maintain backward compatibility + region := auth.Region + if region == "" { + region = "eu-west-2" + } + service := auth.Service + if service == "" { + service = "oapi" + } + + // Compute payload hash from the request body + var payloadHash string + if body == nil { + // Empty body + hash := sha256.Sum256([]byte("")) + payloadHash = hex.EncodeToString(hash[:]) + } else { + // Hash the actual body content + bodyBytes := []byte(body.String()) + hash := sha256.Sum256(bodyBytes) + payloadHash = hex.EncodeToString(hash[:]) + } + + // Sign the request with the computed payload hash + signer := awsv4.NewSigner() + err = signer.SignHTTP(ctx, creds, localVarRequest, payloadHash, service, region, time.Now()) + if err != nil { + return nil, err + } + } + {{/withAWSV4Signature}} + } + + for header, value := range c.cfg.DefaultHeader { + localVarRequest.Header.Add(header, value) + } +{{#withCustomMiddlewareFunction}} + + if c.cfg.Middleware != nil { + c.cfg.Middleware(localVarRequest) + } + + if c.cfg.MiddlewareWithError != nil { + err = c.cfg.MiddlewareWithError(localVarRequest) + if err != nil { + return nil, err + } + } + +{{/withCustomMiddlewareFunction}} +{{#hasHttpSignatureMethods}} + if ctx != nil { + // HTTP Signature Authentication. All request headers must be set (including default headers) + // because the headers may be included in the signature. + if auth, ok := ctx.Value(ContextHttpSignatureAuth).(HttpSignatureAuth); ok { + err = SignRequest(ctx, localVarRequest, auth) + if err != nil { + return nil, err + } + } + } +{{/hasHttpSignatureMethods}} + return localVarRequest, nil +} + +func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) { + if len(b) == 0 { + return nil + } + if s, ok := v.(*string); ok { + *s = string(b) + return nil + } + if f, ok := v.(*os.File); ok { + f, err = os.CreateTemp("", "HttpClientFile") + if err != nil { + return + } + _, err = f.Write(b) + if err != nil { + return + } + _, err = f.Seek(0, io.SeekStart) + return + } + if f, ok := v.(**os.File); ok { + *f, err = os.CreateTemp("", "HttpClientFile") + if err != nil { + return + } + _, err = (*f).Write(b) + if err != nil { + return + } + _, err = (*f).Seek(0, io.SeekStart) + return + } + if XmlCheck.MatchString(contentType) { + if err = xml.Unmarshal(b, v); err != nil { + return err + } + return nil + } + if JsonCheck.MatchString(contentType) { + if actualObj, ok := v.(interface{ GetActualInstance() interface{} }); ok { // oneOf, anyOf schemas + if unmarshalObj, ok := actualObj.(interface{ UnmarshalJSON([]byte) error }); ok { // make sure it has UnmarshalJSON defined + if err = unmarshalObj.UnmarshalJSON(b); err != nil { + return err + } + } else { + return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined") + } + } else if err = json.Unmarshal(b, v); err != nil { // simple model + return err + } + return nil + } + return errors.New("undefined response type") +} + +// Add a file to the multipart request +func addFile(w *multipart.Writer, fieldName, path string) error { + file, err := os.Open(filepath.Clean(path)) + if err != nil { + return err + } + defer file.Close() + + part, err := w.CreateFormFile(fieldName, filepath.Base(path)) + if err != nil { + return err + } + _, err = io.Copy(part, file) + + return err +} + +// Set request body from an interface{} +func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) { + if bodyBuf == nil { + bodyBuf = &bytes.Buffer{} + } + + if reader, ok := body.(io.Reader); ok { + _, err = bodyBuf.ReadFrom(reader) + } else if fp, ok := body.(*os.File); ok { + _, err = bodyBuf.ReadFrom(fp) + } else if b, ok := body.([]byte); ok { + _, err = bodyBuf.Write(b) + } else if s, ok := body.(string); ok { + _, err = bodyBuf.WriteString(s) + } else if s, ok := body.(*string); ok { + _, err = bodyBuf.WriteString(*s) + } else if JsonCheck.MatchString(contentType) { + err = json.NewEncoder(bodyBuf).Encode(body) + } else if XmlCheck.MatchString(contentType) { + var bs []byte + bs, err = xml.Marshal(body) + if err == nil { + bodyBuf.Write(bs) + } + } + + if err != nil { + return nil, err + } + + if bodyBuf.Len() == 0 { + err = fmt.Errorf("invalid body type %s\n", contentType) + return nil, err + } + return bodyBuf, nil +} + +// detectContentType method is used to figure out `Request.Body` content type for request header +func detectContentType(body interface{}) string { + contentType := "text/plain; charset=utf-8" + kind := reflect.TypeOf(body).Kind() + + switch kind { + case reflect.Struct, reflect.Map, reflect.Ptr: + contentType = "application/json; charset=utf-8" + case reflect.String: + contentType = "text/plain; charset=utf-8" + default: + if b, ok := body.([]byte); ok { + contentType = http.DetectContentType(b) + } else if kind == reflect.Slice { + contentType = "application/json; charset=utf-8" + } + } + + return contentType +} + +// Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go +type cacheControl map[string]string + +func parseCacheControl(headers http.Header) cacheControl { + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc +} + +// CacheExpires helper function to determine remaining time before repeating a request. +func CacheExpires(r *http.Response) time.Time { + // Figure out when the cache expires. + var expires time.Time + now, err := time.Parse(time.RFC1123, r.Header.Get("date")) + if err != nil { + return time.Now() + } + respCacheControl := parseCacheControl(r.Header) + + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err := time.ParseDuration(maxAge + "s") + if err != nil { + expires = now + } else { + expires = now.Add(lifetime) + } + } else { + expiresHeader := r.Header.Get("Expires") + if expiresHeader != "" { + expires, err = time.Parse(time.RFC1123, expiresHeader) + if err != nil { + expires = now + } + } + } + return expires +} + +func strlen(s string) int { + return utf8.RuneCountInString(s) +} + +// GenericOpenAPIError Provides access to the body, error and model on returned errors. +type GenericOpenAPIError struct { + body []byte + error string + model interface{} +} + +// Error returns non-empty string if there was an error. +func (e GenericOpenAPIError) Error() string { + return e.error +} + +// Body returns the raw bytes of the response +func (e GenericOpenAPIError) Body() []byte { + return e.body +} + +// Model returns the unpacked model of the error +func (e GenericOpenAPIError) Model() interface{} { + return e.model +} + +// format error message using title and detail when model implements rfc7807 +func formatErrorMessage(status string, v interface{}) string { + str := "" + metaValue := reflect.ValueOf(v).Elem() + + if metaValue.Kind() == reflect.Struct { + field := metaValue.FieldByName("Title") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s", field.Interface()) + } + + field = metaValue.FieldByName("Detail") + if field != (reflect.Value{}) { + str = fmt.Sprintf("%s (%s)", str, field.Interface()) + } + } + + return strings.TrimSpace(fmt.Sprintf("%s %s", status, str)) +} diff --git a/languages/golang/templates/configuration.mustache b/languages/golang/templates/configuration.mustache new file mode 100644 index 0000000..5e9fa90 --- /dev/null +++ b/languages/golang/templates/configuration.mustache @@ -0,0 +1,94 @@ +{{! This template was ENTIRELY overwritten to support the custom configuration type and options from the STACKIT SDK core module. See https://github.com/OpenAPITools/openapi-generator/blob/v7.20.0/modules/openapi-generator/src/main/resources/go/configuration.mustache for the original template }} +{{>partial_header}} +package {{packageName}} + +import ( + "github.com/stackitcloud/stackit-sdk-go/core/config" +) +{{! TEMPLATE CUSTOMIZATION - Template was entirely customized, see above. }} + +// NewConfiguration returns a new Configuration object +func NewConfiguration() *config.Configuration { + cfg := &config.Configuration{ + DefaultHeader: make(map[string]string), + UserAgent: "{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/go{{/httpUserAgent}}", + Debug: false, + {{#servers}} + {{#-first}} + Servers: config.ServerConfigurations{ + {{/-first}} + { + URL: "{{{url}}}", + Description: "{{{description}}}{{^description}}No description provided{{/description}}", + {{#variables}} + {{#-first}} + Variables: map[string]config.ServerVariable{ + {{/-first}} + "{{{name}}}": { + Description: "{{{description}}}{{^description}}No description provided{{/description}}", + DefaultValue: "{{{defaultValue}}}", + {{#enumValues}} + {{#-first}} + EnumValues: []string{ + {{/-first}} + "{{{.}}}", + {{#-last}} + }, + {{/-last}} + {{/enumValues}} + }, + {{#-last}} + }, + {{/-last}} + {{/variables}} + }, + {{#-last}} + }, + {{/-last}} + {{/servers}} + {{#apiInfo}} + OperationServers: map[string]config.ServerConfigurations{ + {{#apis}} + {{#operations}} + {{#operation}} + {{#servers}} + {{#-first}} + "{{{classname}}}Service.{{{nickname}}}": { + {{/-first}} + { + URL: "{{{url}}}", + Description: "{{{description}}}{{^description}}No description provided{{/description}}", + {{#variables}} + {{#-first}} + Variables: map[string]config.ServerVariable{ + {{/-first}} + "{{{name}}}": config.ServerVariable{ + Description: "{{{description}}}{{^description}}No description provided{{/description}}", + DefaultValue: "{{{defaultValue}}}", + {{#enumValues}} + {{#-first}} + EnumValues: []string{ + {{/-first}} + "{{{.}}}", + {{#-last}} + }, + {{/-last}} + {{/enumValues}} + }, + {{#-last}} + }, + {{/-last}} + {{/variables}} + }, + {{#-last}} + }, + {{/-last}} + {{/servers}} + {{/operation}} + {{/operations}} + {{/apis}} + }, + {{/apiInfo}} + } + return cfg +} diff --git a/languages/golang/templates/custom/api_mock.mustache b/languages/golang/templates/custom/api_mock.mustache new file mode 100644 index 0000000..f3475e3 --- /dev/null +++ b/languages/golang/templates/custom/api_mock.mustache @@ -0,0 +1,47 @@ +{{>partial_header}} +package {{packageName}} + +{{#operations}} +import ( + "context" + "net/http" +) + +// assert the implementation matches the interface +var _ {{classname}} = &{{classname}}ServiceMock{} + +// {{classname}}ServiceMock is meant to be used for testing only as a replacement for {{classname}}Service. +// By default all FooExecute() implementations are a no-op. Behavior of the mock can be customized by populating the callbacks in this struct. +type {{classname}}ServiceMock struct { + {{#operation}} + // {{#isDeprecated}}Deprecated: {{/isDeprecated}}{{nickname}}ExecuteMock can be populated to implement the behavior of the {{nickname}}Execute function of this mock + {{nickname}}ExecuteMock *func(r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) + {{/operation}} +} + +{{#operation}} +{{#isDeprecated}} +// Deprecated +{{/isDeprecated}} +func (a {{{classname}}}ServiceMock) {{{nickname}}}(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request { + return {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request{ + ApiService: a, + ctx: ctx, + {{#pathParams}} + {{paramName}}: {{paramName}}, + {{/pathParams}} + } +} + +// {{#isDeprecated}}Deprecated: {{/isDeprecated}}{{nickname}}Execute is a no-op by default and will return only return nil values. Behavior can be controlled by populating the {{nickname}}ExecuteMock field in the {{classname}}ServiceMock struct. +func (a {{{classname}}}ServiceMock) {{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) { + if a.{{nickname}}ExecuteMock == nil { + return {{#returnType}}nil, {{/returnType}}&http.Response{}, nil + } + + return (*a.{{nickname}}ExecuteMock)(r) +} + +{{/operation}} + +{{/operations}} diff --git a/scripts/generate-sdk/generate-sdk.sh b/scripts/generate-sdk/generate-sdk.sh index 2ab94ea..8020bf8 100755 --- a/scripts/generate-sdk/generate-sdk.sh +++ b/scripts/generate-sdk/generate-sdk.sh @@ -55,7 +55,7 @@ fi case "${LANGUAGE}" in go) # When the GENERATOR_VERSION changes, migrate also the templates in templates/go - GENERATOR_VERSION="v6.6.0" # There are issues with GO SDK generation in version v7 + GENERATOR_VERSION="v7.20.0" ;; python) # When the GENERATOR_VERSION changes, migrate also the templates in templates/python diff --git a/scripts/generate-sdk/languages/go.sh b/scripts/generate-sdk/languages/go.sh index 714d333..a0623e3 100644 --- a/scripts/generate-sdk/languages/go.sh +++ b/scripts/generate-sdk/languages/go.sh @@ -16,8 +16,6 @@ SCRIPTS_FOLDER="${SDK_REPO_LOCAL_PATH}/scripts" GENERATOR_LOG_LEVEL="error" # Must be a Java log level (error, warn, info...) -SDK_GO_VERSION="1.21" - generate_go_sdk() { # Required parameters local GENERATOR_JAR_PATH=$1 @@ -105,14 +103,18 @@ generate_go_sdk() { cd "${SDK_REPO_LOCAL_PATH}/core" go work use . fi + + # see https://openapi-generator.tech/docs/file-post-processing/ + export GO_POST_PROCESS_FILE="gofmt -w" warning="" - # Generate SDK for each service - for service_json in ${ROOT_DIR}/oas/legacy/*.json; do - service="${service_json##*/}" + for service_dir in "${ROOT_DIR}/oas/services"/*; do + service="${service_dir##*/}" service="${service%.json}" + compat_layer_service_oas_name="${service}" + # Remove invalid characters to ensure a valid Go pkg name service="${service//-/}" # remove dashes service="${service// /}" # remove empty spaces @@ -121,6 +123,7 @@ generate_go_sdk() { service=$(echo "${service}" | tr -d -c '[:alnum:]') # remove non-alphanumeric characters go_pkg_name_format="^[a-z0-9]+$" + echo "${service_dir}" if [[ ! ${service} =~ ${go_pkg_name_format} ]]; then # check that it is a single lower case word echo "Service ${service} has an invalid Go package name even after removing invalid characters. The generate-sdk.sh script might need to be updated to catch corner case, contact the repo maintainers." exit 1 @@ -132,28 +135,111 @@ generate_go_sdk() { exit 1 fi + # check if the whole service is blocklisted if grep -E "^$service$" "${ROOT_DIR}/languages/golang/blocklist.txt"; then echo "Skipping blocklisted service ${service}" warning+="Skipping blocklisted service ${service}\n" continue fi + + + echo -e "\n>> Generating SDK for \"${service}\" service..." + for version_dir in "${service_dir}"/*; do + service_version_json="${version_dir}/${service_dir##*/}.json" + version="${version_dir##*/}" + + # check if that specific API version of the service is blocklisted + if grep -E "^${service}-${version}$" "${ROOT_DIR}/languages/golang/blocklist.txt"; then + echo "Skipping blocklisted API version ${version} of service ${service}" + warning+="Skipping blocklisted API version ${version} of service ${service}\n" + continue + fi + + echo -e "\n>> Generating SDK package \"${version}api\" for \"${service}\" service..." + cd "${ROOT_DIR}" + + mkdir -p "${SERVICES_FOLDER}/${service}/${version}api" + cp "${ROOT_DIR}/languages/golang/.openapi-generator-ignore" "${SERVICES_FOLDER}/${service}/${version}api/.openapi-generator-ignore" + + # Run the generator for Go + java -Dlog.level=${GENERATOR_LOG_LEVEL} -jar ${jar_path} generate \ + --generator-name go \ + --input-spec "${service_version_json}" \ + --output "${SERVICES_FOLDER}/${service}/${version}api" \ + --package-name "${version}api" \ + --enable-post-process-file \ + --git-host "${GIT_HOST}" \ + --git-user-id "${GIT_USER_ID}" \ + --git-repo-id "${GIT_REPO_ID}/services/${service}" \ + --global-property apis,models,modelTests=true,modelDocs=false,apiDocs=false,supportingFiles,apiTests=false\ + --inline-schema-options "SKIP_SCHEMA_REUSE=true" \ + --http-user-agent "stackit-sdk-go/${service}" \ + --reserved-words-mappings type=types \ + --config "${ROOT_DIR}/languages/golang/openapi-generator-config.yml" + + # Remove unnecessary files + rm "${SERVICES_FOLDER}/${service}/${version}api/.openapi-generator-ignore" + rm -r "${SERVICES_FOLDER}/${service}/${version}api/.openapi-generator" + + # If the service version has a wait package files, move them inside the service folder + if [ -d "${sdk_services_backup_dir}/${service}/${version}api/wait" ]; then + echo "Found ${service} \"wait\" package" + cp -r "${sdk_services_backup_dir}/${service}/${version}api/wait" "${SERVICES_FOLDER}/${service}/${version}api/wait" + fi + done + + if ! grep -E "^$service$" "${ROOT_DIR}/languages/golang/compat-layer/allow-list.txt"; then + echo "Skipping service ${service}, compatibility layer is not activated for it" + warning+="Skipping compatibility layer generation for service ${service}\n" + + cp "${ROOT_DIR}/LICENSE.md" "${SERVICES_FOLDER}/${service}/LICENSE.md" + if [ ! -f "${SERVICES_FOLDER}/${service}/go.mod" ]; then + printf "module github.com/stackitcloud/stackit-sdk-go/services/${service}\n\n" > "${SERVICES_FOLDER}/${service}/go.mod" + printf "go ${SDK_GO_VERSION}\n\n" >> "${SERVICES_FOLDER}/${service}/go.mod" + printf "require (\n\tgithub.com/stackitcloud/stackit-sdk-go/core v0.21.1\n)\n" >> "${SERVICES_FOLDER}/${service}/go.mod" + fi + + # generate package.go + printf "package ${service}\n" > "${SERVICES_FOLDER}/${service}/package.go" + + + cd "${SERVICES_FOLDER}/${service}" + go work use . + # Make sure that dependencies are uptodate + go get -u ./... + go mod tidy + + continue + fi + + # COMPAT LAYER - LEGACY !! - START + + # Download OpenAPI generator if not already downloaded + compat_layer_jar_path="${ROOT_DIR}/scripts/bin/openapi-generator-cli-go-compat-layer.jar" + if [ -e ${compat_layer_jar_path} ] && [ $(java -jar ${compat_layer_jar_path} version) == "6.6.0" ]; then + : + else + echo "Downloading OpenAPI generator (version 6.6.0) for generating the compatibility layer..." + mkdir -p "${ROOT_DIR}/scripts/bin" + wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/6.6.0/openapi-generator-cli-6.6.0.jar -O ${compat_layer_jar_path} --quiet + echo "Download done." + fi - echo -e "\n>> Generating \"${service}\" service..." + echo -e "\n>> Generating compatibility layer for \"${service}\" service..." cd "${ROOT_DIR}" - GO_POST_PROCESS_FILE="gofmt -w" \ - mkdir -p "${SERVICES_FOLDER}/${service}/" + mkdir -p "${SERVICES_FOLDER}/${service}" cp "${ROOT_DIR}/languages/golang/compat-layer/.openapi-generator-ignore" "${SERVICES_FOLDER}/${service}/.openapi-generator-ignore" regional_api= if grep -E "^$service$" ${ROOT_DIR}/languages/golang/compat-layer/regional-allowlist.txt; then echo "Generating new regional api" regional_api="regional_api" fi - - # Run the generator for Go - java -Dlog.level=${GENERATOR_LOG_LEVEL} -jar ${jar_path} generate \ + + # Run the compatibility-layer generator for Go + java -Dlog.level=${GENERATOR_LOG_LEVEL} -jar ${compat_layer_jar_path} generate \ --generator-name go \ - --input-spec "${service_json}" \ + --input-spec "${ROOT_DIR}/oas/legacy/${compat_layer_service_oas_name}.json" \ --output "${SERVICES_FOLDER}/${service}" \ --package-name "${service}" \ --enable-post-process-file \ @@ -186,6 +272,8 @@ generate_go_sdk() { if [ -d "${sdk_services_backup_dir}/${service}/wait" ]; then echo "Found ${service} \"wait\" package" cp -r "${sdk_services_backup_dir}/${service}/wait" "${SERVICES_FOLDER}/${service}/wait" + # deprecate legacy wait package + printf "// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead\npackage wait\n\n" > "${SERVICES_FOLDER}/${service}/wait/deprecation.go" fi # If the service has a CHANGELOG file, move it inside the service folder @@ -211,18 +299,15 @@ generate_go_sdk() { echo "Found ${service} \"VERSION\" file" cp -r "${sdk_services_backup_dir}/${service}/VERSION" "${SERVICES_FOLDER}/${service}/VERSION" fi - - # If the service has oas_commit file, move it inside the service folder - if [ -f "${sdk_services_backup_dir}/${service}/oas_commit" ]; then - echo "Found ${service} \"oas_commit\" file" - cp -r "${sdk_services_backup_dir}/${service}/oas_commit" "${SERVICES_FOLDER}/${service}/oas_commit" - fi - + cd "${SERVICES_FOLDER}/${service}" go work use . # Make sure that dependencies are uptodate go get -u ./... go mod tidy + + # COMPAT LAYER - LEGACY !! - END + done # Add examples to workspace diff --git a/scripts/generate-sdk/languages/java.sh b/scripts/generate-sdk/languages/java.sh index de81419..326c121 100644 --- a/scripts/generate-sdk/languages/java.sh +++ b/scripts/generate-sdk/languages/java.sh @@ -116,6 +116,9 @@ generate_java_sdk() { SERVICE_DESCRIPTION=$(cat "${service_json}" | jq .info.title --raw-output) + # TODO: add to generator below when adding multi-API-version support: + # --inline-schema-options "SKIP_SCHEMA_REUSE=true" + # Run the generator java -Dlog.level="${GENERATOR_LOG_LEVEL}" -jar "${GENERATOR_JAR_PATH}" generate \ --generator-name java \ diff --git a/scripts/generate-sdk/languages/python.sh b/scripts/generate-sdk/languages/python.sh index f5e060f..3fcb53e 100644 --- a/scripts/generate-sdk/languages/python.sh +++ b/scripts/generate-sdk/languages/python.sh @@ -80,6 +80,9 @@ generate_python_sdk() { warning="" + # TODO: add to generator below when adding multi-API-version support: + # --inline-schema-options "SKIP_SCHEMA_REUSE=true" + # Generate SDK for each service for service_json in ${ROOT_DIR}/oas/legacy/*.json; do service="${service_json##*/}" From 390fbbfa7c83fee8c53e2c758224d2933c7dc44e Mon Sep 17 00:00:00 2001 From: Ruben Hoenle Date: Fri, 27 Feb 2026 11:25:28 +0100 Subject: [PATCH 2/4] add error handling via core package --- languages/golang/templates/api.mustache | 484 +++++++++++++++++++++ languages/golang/templates/client.mustache | 26 +- 2 files changed, 488 insertions(+), 22 deletions(-) create mode 100644 languages/golang/templates/api.mustache diff --git a/languages/golang/templates/api.mustache b/languages/golang/templates/api.mustache new file mode 100644 index 0000000..8049874 --- /dev/null +++ b/languages/golang/templates/api.mustache @@ -0,0 +1,484 @@ +{{! This template was customized to use the GenericOpenAPIError from the core module. See https://github.com/OpenAPITools/openapi-generator/blob/v7.20.0/modules/openapi-generator/src/main/resources/go/api.mustache for the original template }} +{{>partial_header}} +package {{packageName}} + +{{#operations}} +import ( + "bytes" + "context" + "io" + "net/http" + "net/url" +{{#imports}} "{{import}}" +{{/imports}} + {{! TEMPLATE CUSTOMIZATION - BEGIN - capture http request and response in ctx }} + "github.com/stackitcloud/stackit-sdk-go/core/config" + {{! TEMPLATE CUSTOMIZATION - END - capture http request and response in ctx }} + {{! TEMPLATE CUSTOMIZATION - BEGIN - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + {{! TEMPLATE CUSTOMIZATION - END - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} +) + +{{#generateInterfaces}} + +type {{classname}} interface { + {{#operation}} + + /* + {{operationId}} {{{summary}}}{{^summary}}Method for {{operationId}}{{/summary}} + {{#notes}} + + {{{unescapedNotes}}} + {{/notes}} + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}} + @param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}} + @return {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request + {{#isDeprecated}} + + Deprecated + {{/isDeprecated}} + */ + {{{nickname}}}(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request + + // {{nickname}}Execute executes the request{{#returnType}} + // @return {{{.}}}{{/returnType}} + {{#isDeprecated}} + // Deprecated + {{/isDeprecated}} + {{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) + {{/operation}} +} +{{/generateInterfaces}} + +// {{classname}}Service {{classname}} service +type {{classname}}Service service +{{#operation}} + +type {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request struct { + ctx context.Context{{#generateInterfaces}} + ApiService {{classname}} +{{/generateInterfaces}}{{^generateInterfaces}} + ApiService *{{classname}}Service +{{/generateInterfaces}} +{{#allParams}} + {{paramName}} {{^isPathParam}}{{^isFile}}*{{/isFile}}{{/isPathParam}}{{{dataType}}} +{{/allParams}} +} + +{{#allParams}} +{{^isPathParam}} +{{#description}} +// {{.}} +{{/description}} +{{#isDeprecated}} +// Deprecated +{{/isDeprecated}} +func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) {{vendorExtensions.x-export-param-name}}({{paramName}} {{{dataType}}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request { + r.{{paramName}} = {{^isFile}}&{{/isFile}}{{paramName}} + return r +} + +{{/isPathParam}} +{{/allParams}} +func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) Execute() ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) { + return r.ApiService.{{nickname}}Execute(r) +} + +/* +{{operationId}} {{{summary}}}{{^summary}}Method for {{operationId}}{{/summary}} +{{#notes}} + +{{{unescapedNotes}}} +{{/notes}} + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}} + @param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}} + @return {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request +{{#isDeprecated}} + +Deprecated +{{/isDeprecated}} +*/ +func (a *{{{classname}}}Service) {{{nickname}}}(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request { + return {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request{ + ApiService: a, + ctx: ctx, + {{#pathParams}} + {{paramName}}: {{paramName}}, + {{/pathParams}} + } +} + +// Execute executes the request{{#returnType}} +// @return {{{.}}}{{/returnType}} +{{#isDeprecated}} +// Deprecated +{{/isDeprecated}} +func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) { + var ( + localVarHTTPMethod = http.Method{{httpMethod}} + localVarPostBody interface{} + formFiles []formFile + {{#returnType}} + localVarReturnValue {{^isArray}}{{^returnTypeIsPrimitive}}{{^isResponseFile}}*{{/isResponseFile}}{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}} + {{/returnType}} + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "{{{classname}}}Service.{{{nickname}}}") + if err != nil { + {{! TEMPLATE CUSTOMIZATION - BEGIN - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, &oapierror.GenericOpenAPIError{ErrorMessage: err.Error()} + {{! TEMPLATE CUSTOMIZATION - END - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + } + + localVarPath := localBasePath + "{{{path}}}"{{#pathParams}} + localVarPath = strings.Replace(localVarPath, "{"+"{{{baseName}}}"+"}", url.PathEscape(parameterValueToString(r.{{paramName}}, "{{paramName}}")), -1){{/pathParams}} + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + {{#allParams}} + {{#required}} + {{^isPathParam}} + if r.{{paramName}} == nil { + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} is required and must be specified") + } + {{/isPathParam}} + {{#minItems}} + if len({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) < {{minItems}} { + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must have at least {{minItems}} elements") + } + {{/minItems}} + {{#maxItems}} + if len({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) > {{maxItems}} { + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must have less than {{maxItems}} elements") + } + {{/maxItems}} + {{#minLength}} + if strlen({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) < {{minLength}} { + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must have at least {{minLength}} elements") + } + {{/minLength}} + {{#maxLength}} + if strlen({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) > {{maxLength}} { + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must have less than {{maxLength}} elements") + } + {{/maxLength}} + {{#minimum}} + {{#isString}} + {{paramName}}Txt, err := atoi({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) + if {{paramName}}Txt < {{minimum}} { + {{/isString}} + {{^isString}} + if {{^isPathParam}}*{{/isPathParam}}r.{{paramName}} < {{minimum}} { + {{/isString}} + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must be greater than {{minimum}}") + } + {{/minimum}} + {{#maximum}} + {{#isString}} + {{paramName}}Txt, err := atoi({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) + if {{paramName}}Txt > {{maximum}} { + {{/isString}} + {{^isString}} + if {{^isPathParam}}*{{/isPathParam}}r.{{paramName}} > {{maximum}} { + {{/isString}} + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must be less than {{maximum}}") + } + {{/maximum}} + {{/required}} + {{/allParams}} + + {{#queryParams}} + {{#required}} + {{#isCollectionFormatMulti}} + { + t := *r.{{paramName}} + if reflect.TypeOf(t).Kind() == reflect.Slice { + s := reflect.ValueOf(t) + for i := 0; i < s.Len(); i++ { + parameterAddToHeaderOrQuery(localVarQueryParams, "{{{baseName}}}", s.Index(i).Interface(), "{{style}}", "{{collectionFormat}}") + } + } else { + parameterAddToHeaderOrQuery(localVarQueryParams, "{{{baseName}}}", t, "{{style}}", "{{collectionFormat}}") + } + } + {{/isCollectionFormatMulti}} + {{^isCollectionFormatMulti}} + parameterAddToHeaderOrQuery(localVarQueryParams, "{{{baseName}}}", r.{{paramName}}, "{{style}}", "{{collectionFormat}}") + {{/isCollectionFormatMulti}} + {{/required}} + {{^required}} + if r.{{paramName}} != nil { + {{#isCollectionFormatMulti}} + t := *r.{{paramName}} + if reflect.TypeOf(t).Kind() == reflect.Slice { + s := reflect.ValueOf(t) + for i := 0; i < s.Len(); i++ { + parameterAddToHeaderOrQuery(localVarQueryParams, "{{{baseName}}}", s.Index(i).Interface(), "{{style}}", "{{collectionFormat}}") + } + } else { + parameterAddToHeaderOrQuery(localVarQueryParams, "{{{baseName}}}", t, "{{style}}", "{{collectionFormat}}") + } + {{/isCollectionFormatMulti}} + {{^isCollectionFormatMulti}} + parameterAddToHeaderOrQuery(localVarQueryParams, "{{{baseName}}}", r.{{paramName}}, "{{style}}", "{{collectionFormat}}") + {{/isCollectionFormatMulti}} + {{#defaultValue}}} else { + {{#isArray}} + var defaultValue {{{dataType}}} = {{{dataType}}}{{{.}}} + parameterAddToHeaderOrQuery(localVarQueryParams, "{{{baseName}}}", defaultValue, "{{style}}", "{{collectionFormat}}") + r.{{paramName}} = &defaultValue + {{/isArray}} + {{^isArray}} + var defaultValue {{{dataType}}} = {{{.}}} + parameterAddToHeaderOrQuery(localVarQueryParams, "{{{baseName}}}", defaultValue, "{{style}}", "{{collectionFormat}}") + r.{{paramName}} = &defaultValue + {{/isArray}} + {{/defaultValue}}} + {{/required}} + {{/queryParams}} + // to determine the Content-Type header +{{=<% %>=}} + localVarHTTPContentTypes := []string{<%#consumes%>"<%&mediaType%>"<%^-last%>, <%/-last%><%/consumes%>} +<%={{ }}=%> + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header +{{=<% %>=}} + localVarHTTPHeaderAccepts := []string{<%#produces%>"<%&mediaType%>"<%^-last%>, <%/-last%><%/produces%>} +<%={{ }}=%> + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } +{{#headerParams}} + {{#required}} + parameterAddToHeaderOrQuery(localVarHeaderParams, "{{{baseName}}}", r.{{paramName}}, "{{style}}", "{{collectionFormat}}") + {{/required}} + {{^required}} + if r.{{paramName}} != nil { + parameterAddToHeaderOrQuery(localVarHeaderParams, "{{{baseName}}}", r.{{paramName}}, "{{style}}", "{{collectionFormat}}") + } + {{/required}} +{{/headerParams}} +{{#formParams}} +{{#isFile}} +{{#isArray}} + var {{paramName}}LocalVarFormFileName string + var {{paramName}}LocalVarFileName string + var {{paramName}}LocalVarFileBytes []byte + + {{paramName}}LocalVarFormFileName = "{{{baseName}}}" + {{paramName}}LocalVarFile := r.{{paramName}} + + if {{paramName}}LocalVarFile != nil { + // loop through the array to prepare multiple files upload + for _, {{paramName}}LocalVarFileValue := range {{paramName}}LocalVarFile { + fbs, _ := io.ReadAll({{paramName}}LocalVarFileValue) + + {{paramName}}LocalVarFileBytes = fbs + {{paramName}}LocalVarFileName = {{paramName}}LocalVarFileValue.Name() + {{paramName}}LocalVarFileValue.Close() + formFiles = append(formFiles, formFile{fileBytes: {{paramName}}LocalVarFileBytes, fileName: {{paramName}}LocalVarFileName, formFileName: {{paramName}}LocalVarFormFileName}) + } + } +{{/isArray}} +{{^isArray}} + var {{paramName}}LocalVarFormFileName string + var {{paramName}}LocalVarFileName string + var {{paramName}}LocalVarFileBytes []byte + + {{paramName}}LocalVarFormFileName = "{{{baseName}}}" + {{paramName}}LocalVarFile := r.{{paramName}} + + if {{paramName}}LocalVarFile != nil { + fbs, _ := io.ReadAll({{paramName}}LocalVarFile) + + {{paramName}}LocalVarFileBytes = fbs + {{paramName}}LocalVarFileName = {{paramName}}LocalVarFile.Name() + {{paramName}}LocalVarFile.Close() + formFiles = append(formFiles, formFile{fileBytes: {{paramName}}LocalVarFileBytes, fileName: {{paramName}}LocalVarFileName, formFileName: {{paramName}}LocalVarFormFileName}) + } +{{/isArray}} +{{/isFile}} +{{^isFile}} +{{#required}} + parameterAddToHeaderOrQuery(localVarFormParams, "{{{baseName}}}", r.{{paramName}}, "{{style}}", "{{collectionFormat}}") +{{/required}} +{{^required}} +{{#isModel}} + if r.{{paramName}} != nil { + paramJson, err := parameterToJson(*r.{{paramName}}) + if err != nil { + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, err + } + localVarFormParams.Add("{{{baseName}}}", paramJson) + } +{{/isModel}} +{{^isModel}} + if r.{{paramName}} != nil { + parameterAddToHeaderOrQuery(localVarFormParams, "{{{baseName}}}", r.{{paramName}}, "{{style}}", "{{collectionFormat}}") + } +{{/isModel}} +{{/required}} +{{/isFile}} +{{/formParams}} +{{#bodyParams}} + // body params + localVarPostBody = r.{{paramName}} +{{/bodyParams}} +{{#authMethods}} +{{#isApiKey}} +{{^isKeyInCookie}} + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + {{#vendorExtensions.x-auth-id-alias}} + if apiKey, ok := auth["{{.}}"]; ok { + var key string + if prefix, ok := auth["{{name}}"]; ok && prefix.Prefix != "" { + key = prefix.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + {{/vendorExtensions.x-auth-id-alias}} + {{^vendorExtensions.x-auth-id-alias}} + if apiKey, ok := auth["{{name}}"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + {{/vendorExtensions.x-auth-id-alias}} + {{#isKeyInHeader}} + localVarHeaderParams["{{keyParamName}}"] = key + {{/isKeyInHeader}} + {{#isKeyInQuery}} + localVarQueryParams.Add("{{keyParamName}}", key) + {{/isKeyInQuery}} + } + } + } +{{/isKeyInCookie}} +{{/isApiKey}} +{{/authMethods}} + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return {{#returnType}}localVarReturnValue, {{/returnType}}nil, err + } + + {{! TEMPLATE CUSTOMIZATION - BEGIN - capture http request and response in ctx }} + contextHTTPRequest, ok := r.ctx.Value(config.ContextHTTPRequest).(**http.Request) + if ok { + *contextHTTPRequest = req + } + {{! TEMPLATE CUSTOMIZATION - END - capture http request and response in ctx }} + + localVarHTTPResponse, err := a.client.callAPI(req) + {{! TEMPLATE CUSTOMIZATION - BEGIN - capture http request and response in ctx }} + contextHTTPResponse, ok := r.ctx.Value(config.ContextHTTPResponse).(**http.Response) + if ok { + *contextHTTPResponse = localVarHTTPResponse + } + {{! TEMPLATE CUSTOMIZATION - END - capture http request and response in ctx }} + if err != nil || localVarHTTPResponse == nil { + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, err + } + +{{#withCustomMiddlewareFunction}} + if a.client.cfg.ResponseMiddleware != nil { + err = a.client.cfg.ResponseMiddleware(localVarHTTPResponse, localVarBody) + if err != nil { + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, err + } + } + +{{/withCustomMiddlewareFunction}} + if localVarHTTPResponse.StatusCode >= 300 { + {{! TEMPLATE CUSTOMIZATION - BEGIN - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + newErr := &oapierror.GenericOpenAPIError{ + Body: localVarBody, + ErrorMessage: localVarHTTPResponse.Status, + StatusCode: localVarHTTPResponse.StatusCode, + } + {{! TEMPLATE CUSTOMIZATION - END - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + {{#responses}} + {{#dataType}} + {{^is1xx}} + {{^is2xx}} + {{#range}} + {{#is3xx}} + if localVarHTTPResponse.StatusCode >= 300 && localVarHTTPResponse.StatusCode < 400 { + {{/is3xx}} + {{#is4xx}} + if localVarHTTPResponse.StatusCode >= 400 && localVarHTTPResponse.StatusCode < 500 { + {{/is4xx}} + {{#is5xx}} + if localVarHTTPResponse.StatusCode >= 500 { + {{/is5xx}} + {{/range}} + {{^range}} + {{^wildcard}} + if localVarHTTPResponse.StatusCode == {{{code}}} { + {{/wildcard}} + {{/range}} + var v {{{dataType}}} + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + {{! TEMPLATE CUSTOMIZATION - BEGIN - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + newErr.ErrorMessage = err.Error() + {{! TEMPLATE CUSTOMIZATION - END - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr + } + {{! TEMPLATE CUSTOMIZATION - BEGIN - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + newErr.ErrorMessage = oapierror.FormatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.Model = v + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr + {{^-last}} + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr + {{/-last}} + {{^wildcard}} + } + {{/wildcard}} + {{/is2xx}} + {{/is1xx}} + {{/dataType}} + {{/responses}} + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr + } + + {{#returnType}} + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + {{! TEMPLATE CUSTOMIZATION - BEGIN - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + newErr := &oapierror.GenericOpenAPIError{ + StatusCode: localVarHTTPResponse.StatusCode, + Body: localVarBody, + ErrorMessage: err.Error(), + } + {{! TEMPLATE CUSTOMIZATION - END - use the GenericOpenAPIError struct from the core module instead of the one generated by OpenAPI generator by default }} + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr + } + + {{/returnType}} + return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, nil +} +{{/operation}} +{{/operations}} diff --git a/languages/golang/templates/client.mustache b/languages/golang/templates/client.mustache index c9ed660..757ea14 100644 --- a/languages/golang/templates/client.mustache +++ b/languages/golang/templates/client.mustache @@ -25,8 +25,9 @@ import ( "unicode/utf8" {{! TEMPLATE CUSTOMIZATION - BEGIN }} - "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/core/auth" + "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" {{! TEMPLATE CUSTOMIZATION - END }} {{#hasOAuthMethods}} @@ -753,27 +754,8 @@ func strlen(s string) int { return utf8.RuneCountInString(s) } -// GenericOpenAPIError Provides access to the body, error and model on returned errors. -type GenericOpenAPIError struct { - body []byte - error string - model interface{} -} - -// Error returns non-empty string if there was an error. -func (e GenericOpenAPIError) Error() string { - return e.error -} - -// Body returns the raw bytes of the response -func (e GenericOpenAPIError) Body() []byte { - return e.body -} - -// Model returns the unpacked model of the error -func (e GenericOpenAPIError) Model() interface{} { - return e.model -} +{{! TEMPLATE CUSTOMIZATION - BEGIN - Remove generation of GenericOpenAPIError struct because we use the one from our core module }} +{{! TEMPLATE CUSTOMIZATION - END - Remove generation of GenericOpenAPIError struct because we use the one from our core module }} // format error message using title and detail when model implements rfc7807 func formatErrorMessage(status string, v interface{}) string { From eb0498591fcf3b758d5f7a24f8b516641dc21160 Mon Sep 17 00:00:00 2001 From: Ruben Hoenle Date: Fri, 27 Feb 2026 12:09:10 +0100 Subject: [PATCH 3/4] unblock CDN --- languages/golang/blocklist.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/languages/golang/blocklist.txt b/languages/golang/blocklist.txt index 33e90f0..fd7a510 100644 --- a/languages/golang/blocklist.txt +++ b/languages/golang/blocklist.txt @@ -10,6 +10,3 @@ pim smokeapi stackitmarketplace support -# CDN beta API versions currently have enums incorrectly defined in the OpenAPI spec -cdn-v1beta -cdn-v1beta2 From 611865f1d91c9131e1f3a216bec1a93d60bd9ea6 Mon Sep 17 00:00:00 2001 From: Ruben Hoenle Date: Fri, 27 Feb 2026 17:53:39 +0100 Subject: [PATCH 4/4] review comments --- scripts/generate-sdk/languages/go.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/generate-sdk/languages/go.sh b/scripts/generate-sdk/languages/go.sh index a0623e3..5257676 100644 --- a/scripts/generate-sdk/languages/go.sh +++ b/scripts/generate-sdk/languages/go.sh @@ -123,7 +123,6 @@ generate_go_sdk() { service=$(echo "${service}" | tr -d -c '[:alnum:]') # remove non-alphanumeric characters go_pkg_name_format="^[a-z0-9]+$" - echo "${service_dir}" if [[ ! ${service} =~ ${go_pkg_name_format} ]]; then # check that it is a single lower case word echo "Service ${service} has an invalid Go package name even after removing invalid characters. The generate-sdk.sh script might need to be updated to catch corner case, contact the repo maintainers." exit 1